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从基础命令到实战之字符串类型
Redis从基础命令到实战之散列类型(Hash)
Redis从基础命令到实战之集合类型(Set)
Redis从基础命令到实战之有序集合类型(SortedSet)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值