前面一篇博文介绍redis五种数据结构中String的使用姿势,这一篇则将介绍另外一个用的比较多的List,对于列表而言,用的最多的场景可以说是当做队列或者堆栈来使用了
I. 基本使用
1. 序列化指定
前面一篇的操作都是直接使用的execute
配合回调方法来说明的,其实还有一种更加方便的方式,即 opsForValue
, opsForList
,本文则以这种方式演示list数据结构的操作
所以在正式开始之前,有必要指定一下key和value的序列化方式,当不现实指定时,采用默认的序列化(即jdk的对象序列化方式),直接导致的就是通过redis-cli获取存储数据时,会发现和你预期的不一样
首先实现序列化类
public class DefaultSerializer implements RedisSerializer<Object> { private final Charset charset; public DefaultSerializer() { this(Charset.forName("UTF8")); } public DefaultSerializer(Charset charset) { Assert.notNull(charset, "Charset must not be null!"); this.charset = charset; } @Override public byte[] serialize(Object o) throws SerializationException { return o == null ? null : String.valueOf(o).getBytes(charset); } @Override public Object deserialize(byte[] bytes) throws SerializationException { return bytes == null ? null : new String(bytes, charset); } } 复制代码
其次定义RedisTemplate的序列化方式
@Configuration public class AutoConfig { @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, String> redis = new RedisTemplate<>(); redis.setConnectionFactory(redisConnectionFactory); // 设置redis的String/Value的默认序列化方式 DefaultSerializer stringRedisSerializer = new DefaultSerializer(); redis.setKeySerializer(stringRedisSerializer); redis.setValueSerializer(stringRedisSerializer); redis.setHashKeySerializer(stringRedisSerializer); redis.setHashValueSerializer(stringRedisSerializer); redis.afterPropertiesSet(); return redis; } } 复制代码
2. 添加元素
对于list而言,添加元素常见的有两种,从左边加和从右边加,以lpush为例
/** * 在列表的最左边塞入一个value * * @param key * @param value */ public void lpush(String key, String value) { redisTemplate.opsForList().leftPush(key, value); } 复制代码
3. 获取元素
既然是list,就是有序的,因此完全是可以向jdk的list容器一样,获取指定索引的值
/** * 获取指定索引位置的值, index为-1时,表示返回的是最后一个;当index大于实际的列表长度时,返回null * * @param key * @param index * @return */ public String index(String key, int index) { return redisTemplate.opsForList().index(key, index); } 复制代码
与jdk中的List获取某个索引value不同的是,这里的index可以为负数,-1表示最右边的一个,-2则表示最右边的第二个,依次
4. 范围查询
这个查询就类似JDK容器中的List#subList
了,查询指定范围的列表
/** * 获取范围值,闭区间,start和end这两个下标的值都会返回; end为-1时,表示获取的是最后一个; * * 如果希望返回最后两个元素,可以传入 -2, -1 * * @param key * @param start * @param end * @return */ public List<String> range(String key, int start, int end) { return redisTemplate.opsForList().range(key, start, end); } 复制代码
5. 列表长度
/** * 返回列表的长度 * * @param key * @return */ public Long size(String key) { return redisTemplate.opsForList().size(key); } 复制代码
6. 修改
更新List中某个下标的value,也属于比较常见的case了,
/** * 设置list中指定下标的值,采用干的是替换规则, 最左边的下标为0;-1表示最右边的一个 * * @param key * @param index * @param value */ public void set(String key, Integer index, String value) { redisTemplate.opsForList().set(key, index, value); } 复制代码
7. 删除
在接口中没有看到删除指定小标的元素,倒是看到可以根据value进行删除,以及控制列表长度的方法
/** * 删除列表中值为value的元素,总共删除count次; * * 如原来列表为 【1, 2, 3, 4, 5, 2, 1, 2, 5】 * 传入参数 value=2, count=1 表示删除一个列表中value为2的元素 * 则执行后,列表为 【1, 3, 4, 5, 2, 1, 2, 5】 * * @param key * @param value * @param count */ public void remove(String key, String value, int count) { redisTemplate.opsForList().remove(key, count, value); } /** * 删除list首尾,只保留 [start, end] 之间的值 * * @param key * @param start * @param end */ public void trim(String key, Integer start, Integer end) { redisTemplate.opsForList().trim(key, start, end); } 复制代码
个人感觉在实际的使用中remove这个方法用得不太多;但是trim方法则比较有用了,特别是在控制list的长度,避免出现非常大的列表时,很有效果,传入的start/end参数,采用的是闭区间的原则