Java中BitMap(位图)hutool版、IntMap、LongMap示例详解
作者:qq_41369135
一、引入依赖
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.5.1</version> </dependency>
二、源码
BitMap (interface )
package cn.hutool.bloomfilter.bitMap; public interface BitMap { int MACHINE32 = 32; int MACHINE64 = 64; void add(long var1); boolean contains(long var1); void remove(long var1); }
IntMap (class)
package cn.hutool.bloomfilter.bitMap; import java.io.Serializable; public class IntMap implements BitMap, Serializable { private static final long serialVersionUID = 1L; private final int[] ints; public IntMap() { this.ints = new int[93750000]; } public IntMap(int size) { this.ints = new int[size]; } public void add(long i) { int r = (int)(i / 32L); int c = (int)(i % 32L); this.ints[r] |= 1 << c; } public boolean contains(long i) { int r = (int)(i / 32L); int c = (int)(i % 32L); return (this.ints[r] >>> c & 1) == 1; } public void remove(long i) { int r = (int)(i / 32L); int c = (int)(i % 32L); int[] var10000 = this.ints; var10000[r] &= ~(1 << c); } }
LongMap(class)
package cn.hutool.bloomfilter.bitMap; import java.io.Serializable; public class LongMap implements BitMap, Serializable { private static final long serialVersionUID = 1L; private final long[] longs; public LongMap() { this.longs = new long[93750000]; } public LongMap(int size) { this.longs = new long[size]; } public void add(long i) { int r = (int)(i / 64L); long c = i % 64L; this.longs[r] |= 1L << (int)c; } public boolean contains(long i) { int r = (int)(i / 64L); long c = i % 64L; return (this.longs[r] >>> (int)c & 1L) == 1L; } public void remove(long i) { int r = (int)(i / 64L); long c = i % 64L; long[] var10000 = this.longs; var10000[r] &= ~(1L << (int)c); } }
三、以下纯属自学(自己测试,有问题请帮忙指出)
四、BigMap原理
原来如果我们要存储1,2,3,4四个整数,就需要new一个 长度为4的数组存储,如new int[3],占内存就是4x4=16byte。而现在入宫hutool的 IntMap,只需要 new IntMap[1]就够了,占内存1x4=4byte。
而且new IntMap[1]可以存储0-31这32个整数。用传统方法得new int[31],占内存就是32x4=128byte。他们两个的内存占比就是32:1(原始:IntMap)
1.IntMap是怎么存储的?add(long i)方法
1.1 我们先new IntMap[1]。int=4byte=32bit。所以得到如下32位二进制 。
00000000 00000000 00000000 00000000
我们都知道二进制只有0和1,在这里可以这么理解,如下面这样,代表存入这个0、7、31三个整数。简而言之,当我们只new 了1字节(32bit)大小的空间, 只要我们存入0-31内的某个数字,二进制对应位就会被置为1
10000000 00000000 00000000 10000001
如:
1.2 查看add方法解析
可以发现他做了以下操作。比如我们要存储 7 这个数字
r 代表7存放在index为0 tmp[0] 里
c 代表 7 该存放在tmp[0] 中32bit位哪个位置
着重 讲 this.ints[r] |= 1 << c (有三步操作),源码是 1左移7位后,第8个bit位从0变为1,如下:
初始 1 的二进制:
00000000 00000000 00000000 00000001
1. 1 左移7位后:
00000000 00000000 00000000 10000000
2. 最后与 ints[0] 进行或运算后得到,如下:
00000000 00000000 00000000 10000000
00000000 00000000 00000000 00000000 ints[0]
结果 :
00000000 00000000 00000000 10000000
3. 第三步,给 ints[0] 赋值 (把或运算的值付给ints[0])
注意:为什么要进行或运算 ,是因为要保留前面add得值。如此时我们已经add了 7 ,此时ints[0]为:
ints[0] = 00000000 00000000 00000000 10000000
我们再往里面 add一个 9 。程序又执行到或运算 那一步
00000000 00000000 00000010 00000000 新的 add 9 的值
00000000 00000000 00000000 10000000 ints[0] 原来add 7 的值
或运算后,7跟9的值都保存起了。如下:
ints[0] = 00000000 00000000 00000010 10000000
个人理解:
接上面第一步 左移7位 说,为什么要从1左移 c 位,我的理解:它的设计思想默认第一个bit位都放余数为0的数,如tmp[0]中的整数0,tmp[1]中的整数 32。其余数 位置都要+1bit位。从代码编写来说就变成 1<<c
2.contains(long i)方法与remove(long i)方法自己可以 根据以上去验证理解
五、同理,LongMap也是类似的思想
到此这篇关于Java中BitMap(位图)hutool版、IntMap、LongMap的文章就介绍到这了,更多相关Java BitMap、IntMap、LongMap内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!