【DB系列】Redis之List数据结构使用姿势

文章目录
  1. I. 基本使用
    1. 1. 序列化指定
    2. 2. 添加元素
    3. 3. 获取元素
    4. 4. 范围查询
    5. 5. 列表长度
    6. 6. 修改
    7. 7. 删除
  2. II. 其他
    1. 0. 项目
    2. 1. 一灰灰Blog
    3. 2. 声明
    4. 3. 扫描关注

前面一篇博文介绍redis五种数据结构中String的使用姿势,这一篇则将介绍另外一个用的比较多的List,对于列表而言,用的最多的场景可以说是当做队列或者堆栈来使用了

I. 基本使用

1. 序列化指定

前面一篇的操作都是直接使用的execute配合回调方法来说明的,其实还有一种更加方便的方式,即 opsForValue, opsForList,本文则以这种方式演示list数据结构的操作

所以在正式开始之前,有必要指定一下key和value的序列化方式,当不现实指定时,采用默认的序列化(即jdk的对象序列化方式),直接导致的就是通过redis-cli获取存储数据时,会发现和你预期的不一样

首先实现序列化类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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的序列化方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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为例

1
2
3
4
5
6
7
8
9
/**
* 在列表的最左边塞入一个value
*
* @param key
* @param value
*/
public void lpush(String key, String value) {
redisTemplate.opsForList().leftPush(key, value);
}

3. 获取元素

既然是list,就是有序的,因此完全是可以向jdk的list容器一样,获取指定索引的值

1
2
3
4
5
6
7
8
9
10
/**
* 获取指定索引位置的值, 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了,查询指定范围的列表

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 获取范围值,闭区间,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. 列表长度

1
2
3
4
5
6
7
8
9
/**
* 返回列表的长度
*
* @param key
* @return
*/
public Long size(String key) {
return redisTemplate.opsForList().size(key);
}

6. 修改

更新List中某个下标的value,也属于比较常见的case了,

1
2
3
4
5
6
7
8
9
10
/**
* 设置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进行删除,以及控制列表长度的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 删除列表中值为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参数,采用的是闭区间的原则

II. 其他

0. 项目

1. 一灰灰Blog

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

2. 声明

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

3. 扫描关注

一灰灰blog

QrCode

知识星球

goals


打赏 如果觉得我的文章对您有帮助,请随意打赏。
分享到