- HyperLogLog
- 采用一种基数算法,用于完成独立总数的统计
- 占据空间小,无论统计多少个数据,只占12k的内存空间
- 使用不精确的统计算法,标准误差为0.81%。
- Bitmap
- 不是一种独立的数据结构,实际上就是字符串。
- 支持按位存取数据,可以将其看成是byte数组。
- 适合存储大量的连续的数据的布尔值
// 统计20万个重复数据的独立总数.
@Test
public void testHyperLogLog() {
String redisKey = "test:hll:01";
for (int i = 1;
i <= 100000;
i++) {
redisTemplate.opsForHyperLogLog().add(redisKey, i);
}for (int i = 1;
i <= 100000;
i++) {
int r = (int) (Math.random() * 100000 + 1);
redisTemplate.opsForHyperLogLog().add(redisKey, r);
}long size = redisTemplate.opsForHyperLogLog().size(redisKey);
System.out.println(size);
}
1)把数据储存到Redis:
生成redisKey
调用API:redisTemplate.opsForHyperLogLog().add(redisKey, i)
2)调用API统计独立总数:
edisTemplate.opsForHyperLogLog().size(redisKey);
2、将3组数据合并, 再统计合并后的重复数据的独立总数.
@Test
public void testHyperLogLogUnion() {
String redisKey2 = "test:hll:02";
for (int i = 1;
i <= 10000;
i++) {
redisTemplate.opsForHyperLogLog().add(redisKey2, i);
}String redisKey3 = "test:hll:03";
for (int i = 5001;
i <= 15000;
i++) {
redisTemplate.opsForHyperLogLog().add(redisKey3, i);
}String redisKey4 = "test:hll:04";
for (int i = 10001;
i <= 20000;
i++) {
redisTemplate.opsForHyperLogLog().add(redisKey4, i);
}String unionKey = "test:hll:union";
redisTemplate.opsForHyperLogLog().union(unionKey, redisKey2, redisKey3, redisKey4);
long size = redisTemplate.opsForHyperLogLog().size(unionKey);
System.out.println(size);
}
1)将三组数据都储存到Redis中
2)调用API合并数据,合并的结果要存放在另一个key里: redisTemplate.opsForHyperLogLog().union(unionKey, redisKey2, redisKey3, redisKey4);
3)调用AP统计独立数据
Bitmap
【牛客网后端项目实战(四十)(Redis高级数据类型介绍)】bitmap不是一个新的数据结构,只是String的一种特殊用法,即按位储存。
1、统计一组数据的布尔值
@Test
public void testBitMap() {
String redisKey = "test:bm:01";
// 记录
redisTemplate.opsForValue().setBit(redisKey, 1, true);
redisTemplate.opsForValue().setBit(redisKey, 4, true);
redisTemplate.opsForValue().setBit(redisKey, 7, true);
// 查询
System.out.println(redisTemplate.opsForValue().getBit(redisKey, 0));
System.out.println(redisTemplate.opsForValue().getBit(redisKey, 1));
System.out.println(redisTemplate.opsForValue().getBit(redisKey, 2));
// 统计
Object obj = redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
return connection.bitCount(redisKey.getBytes());
}
});
System.out.println(obj);
}
1)按位将布尔值存储到字符串中: redisTemplate.opsForValue().setBit(redisKey, 1, true);
参数1,rediskey;参数2,要存储的索引;参数3,要存储的Boolean值
2)查询API,按位查询:redisTemplate.opsForValue().getBit(redisKey, 0)
3)统计,要使用Redis底层的connection
Object obj = redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
return connection.bitCount(redisKey.getBytes());
// 调用connection.bitCount( ),要传递byte数组,所以redisKey.getBytes()
}
});
2、统计3组数据的布尔值, 并对这3组数据做OR运算.
@Test
public void testBitMapOperation() {
String redisKey2 = "test:bm:02";
redisTemplate.opsForValue().setBit(redisKey2, 0, true);
redisTemplate.opsForValue().setBit(redisKey2, 1, true);
redisTemplate.opsForValue().setBit(redisKey2, 2, true);
String redisKey3 = "test:bm:03";
redisTemplate.opsForValue().setBit(redisKey3, 2, true);
redisTemplate.opsForValue().setBit(redisKey3, 3, true);
redisTemplate.opsForValue().setBit(redisKey3, 4, true);
String redisKey4 = "test:bm:04";
redisTemplate.opsForValue().setBit(redisKey4, 4, true);
redisTemplate.opsForValue().setBit(redisKey4, 5, true);
redisTemplate.opsForValue().setBit(redisKey4, 6, true);
String redisKey = "test:bm:or";
Object obj = redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
connection.bitOp(RedisStringCommands.BitOperation.OR,
redisKey.getBytes(), redisKey2.getBytes(), redisKey3.getBytes(), redisKey4.getBytes());
return connection.bitCount(redisKey.getBytes());
}
});
System.out.println(obj);
}
}
1)按位将布尔值存储到字符串中
2)OR操作,同样要使用Redis底层的connection,此外要把OR操作得到的数据存放到新key里
Object obj = redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
connection.bitOp(RedisStringCommands.BitOperation.OR,
redisKey.getBytes(), redisKey2.getBytes(), redisKey3.getBytes(), redisKey4.getBytes());
return connection.bitCount(redisKey.getBytes());
}
});
connection.bitOp():参数1,指定运算符;参数2,指定要存的key;参数3,传递要统计的3组数据
推荐阅读
- Java学习|Spring boot微服务架构中,利用RestTemplate调用别人提供的接口
- 基本类型和包装类
- Java学习|Java>获取Class对象的三种方式,及其Method、Field、Constructor对象的使用方法
- #yyds干货盘点#Java学习18
- java学习|JUC并发编程汇总彻底搞懂JUC
- 安卓逆向之Java学习-03
- Java学习——Applet写字符串(调字体)
- Java学习|[Java] 弄懂数组,这一篇就够了