Java移位运算

来源:互联网 发布:淘宝怎么修改店名 编辑:程序博客网 时间:2024/06/07 14:14

博客理由:景区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));    }}
运算结果:

1010101001010
这就是移位运算的过程,其实对于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年了。