文章目录
  1. Java BitSet基本学习
  2. 1. 基本思想
  3. 2. 场景
    1. 2.1 排序(无重复数据)
    2. 2.2 人群过滤

[TOC]

Java BitSet基本学习

1. 基本思想

Java的BitSet即BitMap。Java中,对于一个整型数字int a = 1,则 a占用4个字节,即32位。对于某些场景而言,这属于巨大的浪费,因为我们可以用 32bit来表示 0~31个十进制数字,而这就是Bitmap的基本思想。

Bitmap可以用来处理大量(海量)数据的排序,查询以及去重。且在做如用户群的交集和并集运算时,也有极大的便利。

2. 场景

2.1 排序(无重复数据)

假设有整型数据如 [4, 10, 2, 18, 24, 11, 8, 1]。如果我们把数据都放到内存中,一个整型需要4个字节,那么总共需要8 * 4 = 32 Byte。那如果我们按如下方式存放:

此时你可以发现只需要4个字节就可以搞定了。那如果有上亿的整数呢,结果可想而知。
看完图你就会发现,数据就已经达到了排序的目的(当然也达到了 去重的目的)。

  • 优点
    • 运算效率高
    • 占用内存少
  • 缺点
    • 数据不能重复

2.2 人群过滤

假设有会员用户活跃用户两个用户群,比如数据如下(都是用户ID):

1
2
会员用户:[1,2,3,4,5,6,7,8,9,10]
活跃用户:[1,3,7,10]

现在需求如下:

  • 取出既是会员又是活跃的用户
  • 取出两部分的用户,保证不重复。
  • 取出不活跃的会员。

方案一:

拿着两组数据直接循环遍历,硬着干。😂要是两组数据都是千万级别,那就很蛋疼了。

方案二:

借助Java的BitSet类。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 会员
private BitSet users1 = new BitSet();
// 活跃用户
private BitSet users2 = new BitSet();

@Before
public void before() {
// 构建会员和活跃用户
Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).forEach(users1::set);
Arrays.asList(1, 3, 7, 10, 12, 20).forEach(users2::set);
}

// 1. 取出既是会员又是活跃的用户
@Test
public void test1() {
users1.and(users2);
System.out.println(users1);
//> {1, 3, 7, 10}
}

// 2. 取出两部分的用户,保证不重复。
@Test
public void test2() {
users1.or(users2);
System.out.println(users1);
//> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 20}
}

// 3. 取出不活跃的会员。
// 也可以直接用users1.andNot(users2);
@Test
public void test3() {
// 取出活跃的会员
users2.and(users1);
// 取出活跃会员不在会员中的用户
users1.xor(users2);
System.out.println(users1);
//> {2, 4, 5, 6, 8, 9}
}
文章目录
  1. Java BitSet基本学习
  2. 1. 基本思想
  3. 2. 场景
    1. 2.1 排序(无重复数据)
    2. 2.2 人群过滤