Redis从基础命令到实战之列表类型(List)
经过上一篇基于Redis散列类型的改造后,实战练习中的商品管理已经具备了增加、修改整体、修改部分属性和分页查询功能,但仍然不支持删除商品的功能。这是因为商品总数是以一个自增数字记录的,且关联了新商品key的生成,删除商品后不能直接减小总数,进而会影响到分页的计算。
在本节中将完善这个功能,使用一个新的数据类型 - 列表类型(List)来保存所有商品ID,计算商品总量时通过计算列表类型长度获得,删除商品时也同时删除列表中的ID。
列表类型用于存储可重复的字符串列表,内部按照添加的先后保持顺序,在列表两端添加和取出元素非常高效,常见的应用场景是社交网站取出最新发表内容列表,也可以用于实现消息队列。先看常用的操作。
一、常用命令
import java.util.List; import redis.clients.jedis.Jedis;
import redis.clients.jedis.SortingParams;
import redis.clients.jedis.BinaryClient.LIST_POSITION; public class ListExample { public static void main(String[] args) {
Jedis jedis = JedisProvider.getJedis();
jedis.flushDB(); //lpush 在左边添加
String fruitKey = "fruit";
long lpush = jedis.lpush(fruitKey, "apple");
print("lpush " + fruitKey + " apple=" + lpush);
lpush = jedis.lpush(fruitKey, "banana");
print("lpush " + fruitKey + " banana=" + lpush);
jedis.lpush(fruitKey, "apple");
jedis.lpush(fruitKey, "apple");
jedis.lpush(fruitKey, "orange");
jedis.lpush(fruitKey, "grape");
jedis.lpush(fruitKey, "peach");
jedis.lpush(fruitKey, "lemon"); //rpush 在右边添加
String numberKey = "numbers";
jedis.rpush(numberKey, "5");
jedis.rpush(numberKey, "4");
jedis.rpush(numberKey, "2");
jedis.rpush(numberKey, "1"); //lrange 获得列表片段
print("lrange " + fruitKey + " [0,-1]=" + jedis.lrange(fruitKey, 0, -1));
print("lrange " + numberKey + " [0,-1]=" + jedis.lrange(numberKey, 0, -1));
print("lrange " + fruitKey + " [1,3]=" + jedis.lrange(fruitKey, 1, 3)); //删除列表指定的值,第二个参数为删除的个数(有重复时),后添加进去的值先被删,类似于出栈,返回删除个数
Long del = jedis.lrem(fruitKey, 2, "apple");
print("lrem " + fruitKey + " apple*2=" + del);
print("after lrem, lrange " + fruitKey + " [0,-1]=" + jedis.lrange(fruitKey, 0, -1)); //删除区间以外的数据, 成功返回 OK
String ltrim = jedis.ltrim(fruitKey, 0, 3);
print("ltrim " + fruitKey + " [0,3]=" + ltrim);
print("after ltrim, lrange " + fruitKey + " [0,-1]=" + jedis.lrange(fruitKey, 0, -1)); //列表元素出栈
String lpop = jedis.lpop(fruitKey);
print("lpop " + fruitKey + " =" + lpop);
print("after lpop, lrange " + fruitKey + " [0,-1]=" + jedis.lrange(fruitKey, 0, -1)); //修改列表中指定下标的值
String lset = jedis.lset(fruitKey, 0, "mango");
print("lset " + fruitKey + " 0=" + lset);
print("after lset, lrange " + fruitKey + " [0,-1]=" + jedis.lrange(fruitKey, 0, -1)); //数组长度
print("llen " + fruitKey + " =" + jedis.llen(fruitKey)); //排序
SortingParams sortingParameters = new SortingParams();
sortingParameters.alpha();
sortingParameters.limit(0, 3);
List<String> list = jedis.sort(fruitKey, sortingParameters);
String sort = "";
for(int i = 0; i < list.size(); i++) {
sort += list.get(i) + " ";
}
print("sort " + fruitKey + " =" + sort); //获取列表指定下标的值, 不存在返回null
int pos = 2;
String lindex = jedis.lindex(fruitKey, pos);
print("lindex " + fruitKey + " 2=" + lindex); //在指定元素前/后插入
jedis.linsert(numberKey, LIST_POSITION.BEFORE, "2", "3");
print("after linsert, lrange " + numberKey + " [0,-1]=" + jedis.lrange(numberKey, 0, -1)); String value = jedis.rpoplpush(numberKey, "dst");
while(value != null) {
System.out.println("rpoplpush " + numberKey + " =" + value);
value = jedis.rpoplpush(numberKey, "dst");
}
print("after rpoplpush, lrange dst [0,-1]=" + jedis.lrange("dst", 0, -1)); jedis.close();
} private static void print(String info) {
System.out.println(info);
System.out.println("------------------------------------------------------");
System.out.println();
}
}
二、实践练习
在上一篇商品管理示例的基础上,增加删除商品的功能。
修改添加商品的功能代码,增加了列表类型保存所有新加入的商品ID
/**
* 添加一个商品
* @param goods
* @return
*/
public boolean addGoods(Goods goods) {
long id = getIncrementId();
Map<String, String> map = new HashMap<>();
map.put("id", String.valueOf(id));
map.put("title", goods.getTitle());
map.put("price", String.valueOf(goods.getPrice()));
String key = "goods:" + id;
boolean added = jedis.hmset(key, map).equals("OK");
if(added) {
jedis.rpush("goods:list", String.valueOf(id));
}
return added;
}
添加删除商品功能代码
/**
* 删除商品
* @param id
* @return
*/
public boolean delGoods(long id) {
long deleted = jedis.del("goods:" + id);
if(deleted == 1) {
jedis.lrem("goods:list", 1, String.valueOf(id));
}
return deleted == 1;
}
还需要修改获得商品总数和分页查询商品的代码,商品总数和ID列表改为从goods:list中获得
/**
* 读取商品总数
* @return
*/
public long getTotalCount() {
String key = "goods:list";
return jedis.llen(key);
}
/**
* 读取用于分页的商品列表
* @param pageIndex 页数
* @param pageSize 每页显示行数
* @return
*/
public List<Goods> getGoodsList(int pageIndex, int pageSize) {
int totals = (int)getTotalCount();
int from = (pageIndex - 1) * pageSize;
if(from < 0) {
from = 0;
}
else if(from > totals) {
from = (totals / pageSize) * pageSize;
}
int to = from + pageSize - 1;
if(to > totals) {
to = totals;
}
List<Goods> goodsList = new ArrayList<>();
List<String> idList = jedis.lrange("goods:list", from, to);
for(String id : idList) {
String key = "goods:" + id;
Map<String, String> maps = jedis.hgetAll(key);
Goods goods = new Goods();
goods.setId(NumberUtils.toLong(maps.get("id")));
goods.setTitle(maps.get("title"));
goods.setPrice(NumberUtils.toFloat(maps.get("price")));
goodsList.add(goods);
}
return goodsList;
}
测试代码
	public static void main(String[] args) {
		ListLession ll = new ListLession();
		ll.clear();
		//添加一批商品
		for(int i = 0; i< 42; i++) {
			Goods goods = new Goods(0, "goods" + String.format("%05d", (i + 1)), i);
			ll.addGoods(goods);
		}
		//读取商品总数
		System.out.println("商品总数: " + ll.getTotalCount());
		//删除第29件商品
		ll.delGoods(29);
		System.out.println("删除后商品总数: " + ll.getTotalCount());
		//分页显示
		List<Goods> list = ll.getGoodsList(2, 20);
		System.out.println("第二页商品:");
		for(Goods goods : list) {
			System.out.println(goods);
		}
	}
现在,商品管理已经具备了增删改查功能,但是Redis还有两个数据类型没有被使用到,下一节将使用集合类型来实现为商品添加分类的功能。
Redis从基础命令到实战之列表类型(List)的更多相关文章
- Redis从基础命令到实战之集合类型(Set)
		
Redis集合类型的基础功能也是存储字符串列表,和列表类型的区别是字符串不能重复且没有顺序.当然,存储元素唯一性也可以通过应用程序保证,单从这一点上并没有体现出对比列表类型的特点. 其实,集合类型的一 ...
 - Redis从基础命令到实战之字符串类型
		
字符串类型是Redis中最基本的数据类型,能存储任何形式的字符串和和二进制数据.本文以代码形式列举常用的操作命令,并在实践部分演示一个简单的商品管理功能,实现了通常使用关系型数据库开发的增改查功能,注 ...
 - Redis从基础命令到实战之有序集合类型(SortedSet)
		
有序集合类型是Redis五种数据类型中最高级的.也是最复杂的类型.有序集合具有集合类型的特性,在其基础上给每个元素关联了一个分值,或称为权重,操作时既可以在添加元素时指定分值,也可以单独修改集合中某一 ...
 - Redis从基础命令到实战之散列类型(Hash)
		
从上一篇的实例中可以看出,用字符串类型存储对象有一些不足,在存储/读取时需要进行序列化/反序列化,即时只想修改一项内容,如价格,也必须修改整个键值.不仅增大开发的复杂度,也增加了不必要的性能开销. 一 ...
 - Redis常用命令入门3:列表类型
		
列表类型 列表类型也是一个我们很长要用到的一个类型.比如我们发博客,要用到博客列表.如果没有列表我们就只能遍历键来获取所有文章或一部分文章了,这个语法是keys,但是这个命令需要遍历数据库中的所有键, ...
 - redis的基础命令操作
		
文章目录 前言 一.字符串类型 二.哈希类型 三.列表类型 四.集合类型 五.有序集合类型 六.通过命令 前言 redis的数据结构 redis存储的是key,value格式的数据,其中的key是字符 ...
 - redis之基础命令
		
一.redis介绍 1.redis特性 Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件 redis是c语言编写的,支持数据持久化,是key-val ...
 - Redis 常用命令学四:列表类型命令
		
1.在列表两端增加值的命令 127.0.0.1:6379> lpush 1 (error) ERR wrong number of arguments for 'lpush' command 1 ...
 - Redis (非关系型数据库) 数据类型 之 list列表类型
		
Redis列表是简单的字符串列表,按照插入顺序排序.你可以添加一个元素到列表的头部(左边)或者尾部(右边) list即可以作为“栈”也可以作为"队列". 操作: >lpush ...
 
随机推荐
- 菜单栏被flex页面遮挡解决办法
 - 解决类似 Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit)的问题
			
源码编译升级安装了gcc后,编译程序或运行其它程序时,有时会出现类似/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found的问题.这 ...
 - [AS3.0] Error #1069: Property onBWDone not found on flash.net.NetConnection and there is no default value.解决办法
			
在运用FMS录制视频时,假如出现这个错误,最直接的解决办法如下: _netConnection.client = { onBWDone: function():void{ trace("on ...
 - windows平台eclipse for C++开发环境搭建
			
参考: 1 blog.sina.com.cn/s/blog_75f3c1f201014l5c.html 2 MinGW官方的安装说明 一.安装并配置MinGW 1 MinGW官网(www.mingw. ...
 - List接口
			
1.List接口实现的方式有两种ArrayList 和 LinkedList ArrayList实现了可变的数组,允许保存所有元素包括null,缺点是删除的比较慢 LinkedList删除对象比较快, ...
 - RabbitMQ(四)
			
RabbitMQ 配置 一.RabbitMQ 配置修改方式 1.修改环境变量 2.修改配置文件(只介绍这个) 3.修改运行时参数和政策 locate rabbitmq vi /var/log/rabb ...
 - git 远程仓库 轻松创建
			
很多时候,为了方面管理我们写的代码,我们采用git 远程仓库来进行管理和备份.防止代码被他人篡改或删除.那如何来进行创建远程仓库呢? 1.我们必须有一个远程服务器端,在这里可以把任意一台电脑作为服务器 ...
 - WPF 容器的Z顺序操作
			
当需要动态添加.修改.删除控件时,如果要达到最好的效果,肯定不只是把需要的控件添加到容器中,并且还需要把容器中的已有控件进行排序操作(置顶.置底.前移.后移操作).由于初次接触到wpf,所以对很多知识 ...
 - Apache RewriteHTTPToHTTPS
			
HTTP to HTTPS Scenario : You want to force people coming to your site to use HTTPS. Either for the e ...
 - 原生态ajax  传递json参数到服务器端
			
案例说明:通过ajax将用户名和密码以json形式传递给服务器端,然后服务器端接受数据,进行处理返回json数据到前端 首先,在客户端,通过JavaScript脚本将页面表单数据封装成JSON格式.L ...