牛客网后端项目实战(四十):Redis高级数据类型介绍

  • HyperLogLog
    • 采用一种基数算法,用于完成独立总数的统计
    • 占据空间小,无论统计多少个数据,只占12k的内存空间
    • 使用不精确的统计算法,标准误差为0.81%。
  • Bitmap
    • 不是一种独立的数据结构,实际上就是字符串。
    • 支持按位存取数据,可以将其看成是byte数组。
    • 适合存储大量的连续的数据的布尔值

简单语法介绍

HyperLogLog

1、统计20万个重复数据的独立总数.

    // 统计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

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学习)