Redis的Hash数据结构操作

416 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

Redis的散列可以让用户将多个键值对存储到一个Redis键里面。

public interface HashOperations<H,HK,HV>

HashOperations提供一系列方法操作hash:

初始化数据:

   redisTemplate.opsForHash().put("test","test1","123");
   redisTemplate.opsForHash().put("test","test2","234");
   redisTemplate.opsForHash().put("test","test3","345");
   redisTemplate.opsForHash().put("test","test4","123");
   redisTemplate.opsForHash().put("test","test5","234");
   redisTemplate.opsForHash().put("test","test6","345");

Long delete(String key); 删除key

redisTemplate.delete("test");
::true|false

Long delete(H key, Object… hashKeys); 删除给定的哈希hashKeys

redisTemplate.opsForHash().delete("test","test1");
::true|false
注意hashKeys不能为空,否则报错 non null hash keys

Boolean hasKey(H key, Object hashKey); 确定哈希hashKey是否存在

redisTemplate.opsForHash().hasKey("test","test1");
::true|false

HV get(H key, Object hashKey); 从键中的哈希获取给定hashKey的值

redisTemplate.opsForHash().get("test","test3");
::345

List multiGet(H key, Collection hashKeys); 从哈希中获取给定hashKey的值

redisTemplate.opsForHash().get("test",Lists.newArrayList("test1","test3","test5"));
::123
::345
::234

Long increment(H key, HK hashKey, long delta); 通过给定的delta增加散列hashKey的值(整型)

hashOperations.increment("ttttttt","t116", 1);

Double increment(H key, HK hashKey, double delta); 通过给定的delta增加散列hashKey的值(浮点数)

hashOperations.increment("ttttttt","t116", 1.1);

异常报错: RedisCommandExecutionException: ERR hash value is not an integer

原因分析:

GenericJackson2JsonRedisSerializer、Jackson2JsonRedisSerializer是先将对象转为json,然后再保存到redis,所以,1在redis中是字符串1,所以无法进行加1 。

JdkSerializationRedisSerializer使用的jdk对象序列化,序列化后的值有类信息、版本号等,所以是一个包含很多字母的字符串,所以根本无法加1。

GenericToStringSerializer、StringRedisSerializer将字符串的值直接转为字节数组,所以保存到redis中是数字,所以可以进行加1 ;通过以下代码配置redistemplate的序列化方式之后就可以顺利的执行increment了。


/**
 * 设置 redisTemplate 的序列化设置
 * @param redisConnectionFactory
 * @return
 */
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    
    template.setConnectionFactory(redisConnectionFactory);
    // 创建 序列化类
    //解决redis的Long的increment自增报错

    GenericToStringSerializer genericToStringSerializer = new GenericToStringSerializer(Object.class);

    // 7.设置 value 的转化格式和 key 的转化格式
    template.setValueSerializer(genericToStringSerializer);
    template.setKeySerializer(new StringRedisSerializer());
    template.afterPropertiesSet();
    return template;
    }
}

Set keys(H key); 获取key所对应的散列表的key

 Set<Object> set = redisTemplate.opsForHash().keys("test");
   System.out.println(set);

Long size(H key); 获取key所对应的散列表的大小个数

Long size = hashOperations.size("ttttttt");

void put(H key, HK hashKey, HV value); 设置散列hashKey的值

redisTemplate.opsForHash().put("test","test1","123");

Boolean putIfAbsent(H key, HK hashKey, HV value); 仅当hashKey不存在时才设置散列hashKey的值。

redisTemplate.opsForHash().putIfAbsent("test","test1","123");

void putAll(H key, Map m); 使用m中提供的多个散列字段设置到key对应的散列表中。

Map map = new HashMap<String, String>();
map.put("ttu","1");
map.put("thu","2");
redisTemplate.opsForHash().putAll("test1",map);

List values(H key) 获取整个哈希存储的值根据密钥。

System.out.println(template.opsForHash().values("ttttttt"));

Map<HK, HV> entries(H key); 获取整个哈希存储根据密钥

使System.out.println(template.opsForHash().entries("ttttttt"));

Cursor<Map.Entry<HK, HV>> scan(H key, ScanOptions options); 使用Cursor在key的hash中迭代,相当于迭代器。

//使用Cursor在key的hash中迭代,相当于迭代器。
Cursor<Map.Entry<String, Long>> curosr = hashOperations.scan("ttttttt", ScanOptions.NONE);
while(curosr.hasNext()){
   Map.Entry<String, Long> entry = curosr.next();
   System.out.println(entry.getKey()+":"+entry.getValue());
}

例子代码:

@GetMapping(value = "hash")
public void hash(){

   redisTemplate.opsForHash().put("test","test1","123");
   redisTemplate.opsForHash().put("test","test2","234");
   redisTemplate.opsForHash().put("test","test3","345");
   redisTemplate.opsForHash().put("test","test4","123");
   redisTemplate.opsForHash().put("test","test5","234");
   redisTemplate.opsForHash().put("test","test6","345");


   Object o = redisTemplate.opsForHash().get("test", "test4");
   System.out.println(o);
   Map<Object, Object> map = redisTemplate.opsForHash().entries("test");
   System.out.println(map);
   Set<Object> set = redisTemplate.opsForHash().keys("test");
   System.out.println(set);
   List<Object> list = redisTemplate.opsForHash().values("test");
   System.out.println(list);
   Set<String> sets = new HashSet(Lists.transform(list, s -> s.toString()));
   System.out.println("list to set:"+sets);
   List<Object> list2 = redisTemplate.opsForHash().multiGet("test", Lists.newArrayList("test1","test3","test5"));
   System.out.println(list2);



//使用Cursor在key的hash中迭代,相当于迭代器。
Cursor<Map.Entry<String, Long>> curosr = hashOperations.scan("ttttttt", ScanOptions.NONE);
while(curosr.hasNext()){
   Map.Entry<String, Long> entry = curosr.next();
   System.out.println(entry.getKey()+":"+entry.getValue());
}


}