Redis之数据结构HashMap详细使用

本文详细介绍如何简化Redis中HashMap数据结构的操作,包括增删改查等核心功能,并提供Java代码示例,帮助开发者更高效地使用Redis。

一般大家使用redis的string数据结构比较多,在想使用其他数据结构,但是感觉操作复杂的现象身边很普遍,
为简化大家操作redis hashmap,特整理此文,方便大家使用。

 

一、Redis数据结构 hashmap,RedisDesktopManager使用如下:

 

 

二、  通过代码 Java端使用

增:

Map<String, UserRankDto> userDtoMap = new HashMap<>();
UserRankDto rankDto = null;
for (Stu stu : stuList) {
	rankDto = new UserRankDto();
	//属性赋值略

	userDtoMap.put(String.valueOf(stu.getUserid()), rankDto);
}
RedisCacheUtils.setMap(AnalysisConstant.REDIS_PERSONAL_MAP, userDtoMap, AnalysisConstant.REDIS_DATABASE_INDEX);


AnalysisConstant.REDIS_PERSONAL_MAP:自定义业务主key
AnalysisConstant.REDIS_DATABASE_INDEX: redis对应的数据库(0-15)
/**
     * 将map写入缓存
     *
     * @param key
     * @param map
     */
    public static <T> void setMap(String key, Map<String, T> map, Integer dbIndex) {
        setMap(key, map, dbIndex, NOT_EXPIRE);
    }

    /**
     * 将map写入缓存
     *
     * @param key
     * @param map
     * @param expire 失效时间(秒)
     */
    public static <T> void setMap(String key, Map<String, T> map, Integer dbIndex, Integer expire) {
        setDbIndex(dbIndex);

        template.opsForHash().putAll(key, map);
        if (expire != NOT_EXPIRE) {
            expire(key, expire);
        }
    }

删:

RedisCacheUtils.deleteByPrefix(AnalysisConstant.REDIS_PERSONAL_MAP, AnalysisConstant.REDIS_DATABASE_INDEX);

/**
 * 删除 指定数据库 前缀模糊匹配 索引
 *
 * @param dbIndex 数据库索引 范围 0-15 默认0
 */
public static void deleteByPrefix(String prefix, Integer dbIndex) {
	setDbIndex(dbIndex);
	Set<String> keys = template.keys(prefix + "*");
	template.delete(keys);
}


/**
 * 删除 指定数据库索引
 *
 * @param key     键
 * @param dbIndex 数据库索引 范围 0-15 默认0
 */
public static void delete(String key, Integer dbIndex) {
	setDbIndex(dbIndex);
	template.delete(key);
}

改:

// 放入hashmap中一个Userid对应值  key - value
// 没有就新增,如果有对应的key为 userid,则覆盖更新
RedisCacheUtils.setMapValue(AnalysisConstant.REDIS_PERSONAL_MAP, String.valueOf(model.getUserid()), userRankDto, AnalysisConstant.REDIS_DATABASE_INDEX);


/**
 * 插入值-对象,指定数据库索引,指定过期时间
 *
 * @param key      键
 * @param mapKey   map键
 * @param mapValue map值
 * @param dbIndex  数据库索引 范围 0-15 默认0
 */
public static <T> void setMapValue(String key, String mapKey, T mapValue, Integer dbIndex) {
	setMapValue(key, mapKey, mapValue, dbIndex, NOT_EXPIRE);
}

/**
 * 插入值-对象,指定数据库索引,指定过期时间
 *
 * @param key      键
 * @param mapKey   map键
 * @param mapValue map值
 * @param dbIndex  数据库索引 范围 0-15 默认0
 * @param expire   过期时间 单位:秒
 */
public static <T> void setMapValue(String key, String mapKey, T mapValue, Integer dbIndex, int expire) {
	// 选择数据库
	setDbIndex(dbIndex);
	BoundHashOperations<String, String, T> boundHashOperations = template.boundHashOps(key);
	boundHashOperations.put(mapKey, mapValue);
	if (expire != NOT_EXPIRE) {
		expire(key, expire);
	}
}

查:

// 获取map中的单个特定key的value值
UserRankDto dto = RedisCacheUtils.getMapValue(AnalysisConstant.REDIS_PERSONAL_MAP,String.valueOf(userId),DB_INDEX);

/**
 * 获取值-字符串,指定数据库索引,设置过期时间
 *
 * @param key     键
 * @param mapKey  map键
 * @param dbIndex 数据库索引 范围 0-15 默认0
 * @return
 */
public static <T> T getMapValue(String key, String mapKey, Integer dbIndex) {
	// 选择数据库
	setDbIndex(dbIndex);
	BoundHashOperations<String, String, T> boundHashOperations = template.boundHashOps(key);
	return boundHashOperations.get(mapKey);
}
// 获取整个hashmap

/**
 * 获取map缓存
 *
 * @param key
 * @return
 */
public static <T> Map<String, T> getMap(String key, Integer dbIndex) {
	setDbIndex(dbIndex);
	BoundHashOperations<String, String, T> boundHashOperations = template.boundHashOps(key);
	return boundHashOperations.entries();
}

补充:

/**
     * redis 模板
     */
    private static StringRedisTemplate template = SpringContextHolder.getBean("stringRedisTemplate");

    /**
     * 不设置过期时长
     */
    public final static int NOT_EXPIRE = -1;

redis版本: 

### ✅ 回答问题: 在 Redis 中,并没有名为 “Map” 的数据类型,但通常我们所说的 **Redis Map** 指的是 **Hash(哈希)** 数据结构Redis Hash 非常类似于 Java 中的 `Map<String, String>` 或 `HashMap`,适合存储对象的字段-值对。 --- ### ✅ 一、Redis Hash 核心特性 | 特性 | 说明 | |------|------| | ✅ 存储键值对集合 | 类似于一个对象(Object),支持多个 field-value | | ✅ 内存高效 | 当字段较少时自动使用 `ziplist` 编码节省内存 | | ✅ 支持部分更新 | 可单独修改某个 field,无需整个重写 | | ✅ 原子操作 | 单个命令是原子性的(如 HSET) | | ✅ 支持批量读写 | 如 `HMSET`, `HMGET`, `HGETALL` | > 💡 适用场景:用户信息、商品详情、配置项等结构化数据存储 --- ### ✅ 二、常用命令与 Java 对应方法 | Redis 命令 | 功能描述 | Spring Data Redis 方法 | |----------|----------|------------------------| | `HSET key field value` | 设置 hash 中的一个字段 | `opsForHash().put(key, field, value)` | | `HGET key field` | 获取指定字段的值 | `opsForHash().get(key, field)` | | `HMSET key field1 val1 field2 val2 ...` | 批量设置多个字段 | `opsForHash().putAll(key, map)` | | `HMGET key field1 field2 ...` | 批量获取多个字段 | `opsForHash().multiGet(key, fields)` | | `HGETALL key` | 获取所有字段和值 | `opsForHash().entries(key)` | | `HEXISTS key field` | 判断字段是否存在 | `opsForHash().hasKey(key, field)` | | `HDEL key field [field ...]` | 删除一个或多个字段 | `opsForHash().delete(key, field...)` | | `HLEN key` | 获取字段数量 | `opsForHash().size(key)` | | `HKEYS key` | 获取所有字段名 | `opsForHash().keys(key)` | | `HVALS key` | 获取所有字段值 | `opsForHash().values(key)` | | `HINCRBY key field increment` | 数字字段自增 | `opsForHash().increment(key, field, delta)` | --- ### ✅ 三、Java 使用示例(Spring Data Redis) #### 🔹 场景1:存储用户信息(替代 JSON 字符串) ```java import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.Map; @Service public class UserService { @Autowired private StringRedisTemplate redisTemplate; private static final String USER_HASH_KEY_PREFIX = "user:info:"; /** * 保存用户信息到 Redis Hash */ public void saveUser(String userId, String name, String email, int age) { String key = USER_HASH_KEY_PREFIX + userId; HashOperations<String, String, String> hashOps = redisTemplate.opsForHash(); // 单个字段设置 hashOps.put(key, "name", name); hashOps.put(key, "email", email); hashOps.put(key, "age", String.valueOf(age)); hashOps.put(key, "updateTime", String.valueOf(System.currentTimeMillis())); } /** * 批量保存用户信息 */ public void saveUserBatch(String userId, Map<String, String> userInfo) { String key = USER_HASH_KEY_PREFIX + userId; redisTemplate.opsForHash().putAll(key, userInfo); } /** * 获取用户某个字段 */ public String getUserField(String userId, String field) { String key = USER_HASH_KEY_PREFIX + userId; return (String) redisTemplate.opsForHash().get(key, field); } /** * 批量获取多个字段 */ public List<String> getUserFields(String userId, List<String> fields) { String key = USER_HASH_KEY_PREFIX + userId; return redisTemplate.opsForHash().multiGet(key, fields); } /** * 获取完整用户信息 */ public Map<Object, Object> getUserInfo(String userId) { String key = USER_HASH_KEY_PREFIX + userId; return redisTemplate.opsForHash().entries(key); } /** * 更新用户年龄(原子自增) */ public void incrementAge(String userId, long delta) { String key = USER_HASH_KEY_PREFIX + userId; redisTemplate.opsForHash().increment(key, "age", delta); } /** * 删除用户某个字段 */ public void removeUserField(String userId, String field) { String key = USER_HASH_KEY_PREFIX + userId; redisTemplate.opsForHash().delete(key, field); } /** * 检查字段是否存在 */ public boolean hasField(String userId, String field) { String key = USER_HASH_KEY_PREFIX + userId; return redisTemplate.opsForHash().hasKey(key, field); } } ``` --- ### ✅ 四、底层编码优化(内存效率) Redis Hash 在以下情况下会自动选择最优编码: | 条件 | 编码方式 | 说明 | |------|--------|------| | 字段数 ≤ `hash-max-ziplist-entries`(默认 512)<br>且所有 value 长度 ≤ `hash-max-ziplist-value`(默认 64 字节) | `ziplist` | 节省内存,连续存储 | | 超出限制 | `hashtable` | 标准哈希表,性能稳定 | > 📌 建议根据业务调整配置: ```conf hash-max-ziplist-entries 512 hash-max-ziplist-value 64 ``` --- ### ✅ 五、典型应用场景 | 场景 | 描述 | |------|------| | 🧑 用户资料缓存 | 存储用户昵称、头像、等级、积分等字段 | | 🛍️ 商品信息缓存 | 缓存 SKU 的价格、库存、标题等,避免频繁查 DB | | ⚙️ 配置中心 | 存储服务的动态配置项,如开关、超时时间 | | 📈 统计指标分组 | 按维度统计 UV、PV:`stats:page:home -> {views:1000, uv:800}` | | 🔐 权限控制 | 存储用户权限列表:`perms:user:1001 -> {read:1, write:0}` | --- ### ✅ 六、注意事项与最佳实践 | 项目 | 建议 | |------|------| | ✅ 小对象优先用 Hash | 比序列化成 JSON 更易维护、更省空间 | | ❌ 不要存储大文本 | 如文章内容,建议用 `String` 或外部存储 | | ✅ 合理设置 TTL | 使用 `EXPIRE user:info:123 3600` 避免内存泄露 | | 💡 批量操作提升性能 | 使用 `HMGET`/`HMSET` 减少网络往返 | | 🔒 并发安全 | 单个 HSET 是原子的;跨 field 操作需 Lua 脚本保证一致性 | --- ### ✅ 七、对比其他方式存储对象 | 方式 | 是否推荐 | 说明 | |------|----------|------| | **Hash** | ✅ 推荐 | 易扩展、支持部分更新、内存友好 | | **String + JSON 序列化** | ⚠️ 视情况 | 适合复杂嵌套对象,但每次全量读写 | | **ZSet** | ❌ 不适用 | 用于排序,不适合字段存储 | | **Multiple Keys** | ❌ 不推荐 | 如 `user:1:name`, `user:1:age`,难以管理 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值