Java移位运算
博客理由:景區APP項目中涉及到分布式ID設計。分別有幾種ID的設計方式:一種是數據庫的自增,但是局限很大;第二種uuid,直接采用jdk自帶的uuid生成即可;第三種是Twitter的Snowflake(雪花)ID生成技術,目前還在研究公開的源碼,但是其中涉及到的移位運算比較多,故寫下此文章回顧移位運算。
Java中有三種移位運算:
num << 位數 ? ?:這種表示num向左移動多少位,一般會用長整型來描述這個num,例如(Snowflake中的時間戳取值范圍)1L << 41,就代表1L毫秒左移41位。
num >> 位數 ? ?:num右移具體位數;
>>> ? ?: 無符號右移,忽略符號位,空位都以0補齊。
先來看一段移位的Demo,然后我來說明一下如何理解Java的移位運算。
package com.b510.test;/*** @author * @create date:2017-11-17* @version 1.0*/ public class Test {public static void main(String[] args) {int number = 10;//原始數二進制printInfo(number);number = number << 1;//左移一位printInfo(number);number = number >> 1;//右移一位printInfo(number);}/*** 輸出一個int的二進制數* @param num*/private static void printInfo(int num){System.out.println(Integer.toBinaryString(num));} }運算結果: 1010 10100 1010這就是移位運算的過程,其實對于Java語言來說,移位運算運用的并不是很多,因此移位運算對于大多數初級開發者來說會感覺到很陌生、很神秘。我們應當這么理解Java中的移位運算:首先移位運算是針對二進制數來說的,由于Java中的整型(int long)都是以十進制表示,因此我們應當明確一點,一個數可以有多種進制的表達形式,我們寫的整型數也同樣可以進行移位運算,當然,移位之后的值,就必須去用二進制的思維去考慮了。
一種常見的應用場景是二進制數的取值范圍,Snowflake中時間戳用41位的二進制表示,那41位的二進制數可以表示多少個1毫秒呢?計算的方式就是1L << 41,其實這個運算可以拆分成兩部分:第一部分1L,第二部分<<41,第一部分代表十進制的1(個)毫秒,第二部分左移41位,實際上在Java底層會將前面的1L轉換成二進制數之后再進行移位運算,最后將結果以長整型的形式輸出出來。
可以用十進制來類比一下,一個十進制的1左移3位是多少?沒錯,是1000,取值范圍是1~999(一般計算的是整數的取值)。
這樣我們就可以理解:為什么Snowflake的41位的時間戳可以用:(1L<< 41) / (1000L * 60 * 60 * 24 * 365) = 69年了。
總結
- 上一篇: Maven学习(六)————企业Mave
- 下一篇: Java常用设计模式————工厂模式