Redis 的 Hash 是一种键值对集合(field-value),适合存储对象类数据(如用户信息、商品属性等)。每个 Hash 可以包含多个字段(field),每个字段对应一个值(value),且字段唯一。以下是基于 Jedis 客户端的 Hash 核心操作示例。

一、基础操作:设置与获取字段

1.1 设置字段值(hset/hmset)

  • hset key field value:为哈希表设置单个字段值,返回 1 表示字段新增,0 表示字段已存在并更新;
  • hmset key field1 value1 field2 value2 ...:批量设置多个字段值(Jedis 中已标记为过时,推荐使用 hset 传入 Map 替代)。

代码示例:

private static void testHset(Jedis jedis) {
    // 清空哈希表(若存在)
    jedis.del("user:100");
    
    // 设置单个字段
    long hsetResult1 = jedis.hset("user:100", "name", "zhangsan");
    System.out.println("设置name结果(1=新增):" + hsetResult1); // 结果:1
    
    // 批量设置字段(推荐方式:传入Map)
    Map<String, String> userInfo = new HashMap<>();
    userInfo.put("age", "25");
    userInfo.put("city", "beijing");
    jedis.hset("user:100", userInfo);
    
    // 更新已有字段
    long hsetResult2 = jedis.hset("user:100", "age", "26");
    System.out.println("更新age结果(0=已存在):" + hsetResult2); // 结果:0
}

1.2 获取字段值(hget/hmget/hgetAll)

  • hget key field:获取单个字段的值,字段不存在返回 null;
  • hmget key field1 field2 ...:批量获取多个字段的值,返回与字段顺序对应的列表;
  • hgetAll key:获取哈希表中所有字段和值,返回包含所有 field-value 的 Map。

代码示例:

private static void testGetHashValues(Jedis jedis) {
    // 假设哈希表 user:100 包含:name=zhangsan, age=26, city=beijing
    
    // 获取单个字段
    String name = jedis.hget("user:100", "name");
    System.out.println("name字段值:" + name); // 结果:zhangsan
    
    // 批量获取字段
    List<String> values = jedis.hmget("user:100", "age", "city");
    System.out.println("age和city的值:" + values); // 结果:[26, beijing]
    
    // 获取所有字段和值
    Map<String, String> allInfo = jedis.hgetAll("user:100");
    System.out.println("所有字段和值:" + allInfo); 
    // 结果:{name=zhangsan, age=26, city=beijing}
}

二、字段管理:判断、删除与数量

2.1 判断字段是否存在(hexists)

hexists key field:返回 true 表示字段存在,false 表示不存在。

代码示例:

private static void testHexists(Jedis jedis) {
    boolean hasName = jedis.hexists("user:100", "name");
    boolean hasGender = jedis.hexists("user:100", "gender");
    System.out.println("name是否存在:" + hasName); // 结果:true
    System.out.println("gender是否存在:" + hasGender); // 结果:false
}

2.2 删除字段(hdel)

hdel key field1 field2 ...:删除一个或多个字段,返回实际删除的字段数量。

代码示例:

private static void testHdel(Jedis jedis) {
    // 删除单个字段
    long delCount1 = jedis.hdel("user:100", "city");
    System.out.println("删除city的数量:" + delCount1); // 结果:1
    
    // 批量删除字段(其中gender不存在)
    long delCount2 = jedis.hdel("user:100", "age", "gender");
    System.out.println("删除age和gender的数量:" + delCount2); // 结果:1
    
    // 查看剩余字段
    System.out.println("剩余字段:" + jedis.hgetAll("user:100")); // 结果:{name=zhangsan}
}

2.3 获取字段数量(hlen)

hlen key:返回哈希表中字段的总个数。

代码示例:

private static void testHlen(Jedis jedis) {
    long fieldCount = jedis.hlen("user:100");
    System.out.println("字段总数:" + fieldCount); // 结果:1(仅name字段剩余)
}

三、批量操作:获取所有字段或值

3.1 获取所有字段名(hkeys)

hkeys key:返回哈希表中所有字段的名称,以 Set 形式返回。

代码示例:

private static void testHkeys(Jedis jedis) {
    // 重新添加字段:age=26, city=beijing
    jedis.hset("user:100", "age", "26");
    jedis.hset("user:100", "city", "beijing");
    
    Set<String> fields = jedis.hkeys("user:100");
    System.out.println("所有字段名:" + fields); // 结果:[name, age, city]
}

3.2 获取所有字段值(hvals)

hvals key:返回哈希表中所有字段的值,以 List 形式返回。

代码示例:

private static void testHvals(Jedis jedis) {
    List<String> values = jedis.hvals("user:100");
    System.out.println("所有字段值:" + values); // 结果:[zhangsan, 26, beijing]
}

四、数值增减:hincrBy

hincrBy key field increment:对哈希表中指定字段的数值进行增减(increment 为正数时自增,负数时自减),字段不存在时默认初始值为 0。

场景:适合统计类字段(如商品销量、用户积分等)。

代码示例:

private static void testHincrBy(Jedis jedis) {
    // 初始化商品销量字段
    jedis.hset("product:100", "sales", "100");
    
    // 销量增加20
    long newSales1 = jedis.hincrBy("product:100", "sales", 20);
    System.out.println("增加20后销量:" + newSales1); // 结果:120
    
    // 销量减少5
    long newSales2 = jedis.hincrBy("product:100", "sales", -5);
    System.out.println("减少5后销量:" + newSales2); // 结果:115
    
    // 对不存在的字段增减(默认初始值0)
    long stock = jedis.hincrBy("product:100", "stock", 50);
    System.out.println("初始化库存:" + stock); // 结果:50
}

五、常用场景总结

  1. 存储对象:用 Hash 存储用户、商品等对象的属性(如 user:100 存储用户ID=100的信息),相比 String 类型更节省空间且便于单独更新字段;
  2. 统计数据:通过 hincrBy 实现计数器(如商品销量、页面访问量);
  3. 配置管理:存储系统配置项,支持单独修改某个配置字段。

更多推荐