zoukankan      html  css  js  c++  java
  • Redis从基础命令到实战之有序集合类型(SortedSet)

    有序集合类型是Redis五种数据类型中最高级的、也是最复杂的类型。有序集合具有集合类型的特性,在其基础上给每个元素关联了一个分值,或称为权重,操作时既可以在添加元素时指定分值,也可以单独修改集合中某一个元素的分值。使用时可以按分值排序(从低到高或从高到低)并顺序读取全部或某一范围内的元素,或者获得某一分值范围内的元素。利用这一特点,可以很方便的实现排行榜、热门文章等功能。

    在本节的实例中,使用有序集合类型为商品管理模块添加一个按浏览量排序的功能。

    一、常用命令

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. import java.util.Set;  
    2.   
    3. import redis.clients.jedis.Jedis;  
    4. import redis.clients.jedis.Tuple;  
    5.   
    6. public class SortedSetExample {  
    7.   
    8.     public static void main(String[] args) {  
    9.         Jedis jedis = JedisProvider.getJedis();  
    10.         jedis.flushDB();  
    11.   
    12.         // 向有序集合中加入元素, 成功返回1, 失败返回0  
    13.         Long zadd = jedis.zadd("fruit", 5.0, "apple");  
    14.         print("zadd fruit apple=" + zadd);  
    15.         // 重复添加, 会修改权重  
    16.         zadd = jedis.zadd("fruit", 6.0, "apple");  
    17.         print("zadd fruit apple again=" + zadd);  
    18.   
    19.         jedis.zadd("fruit", 2.0, "banana");  
    20.         jedis.zadd("fruit", 4.0, "orange");  
    21.         jedis.zadd("fruit", 8.0, "grape");  
    22.         jedis.zadd("fruit", 10.0, "lemon");  
    23.         jedis.zadd("fruit", 7.0, "cherry");  
    24.           
    25.         // 统计元素个数  
    26.         print("zcard fruit=" + jedis.zcard("fruit"));  
    27.           
    28.         // 统计某个权重范围内元素个数  
    29.         print("zcount fruit [1.0,5.0]=" + jedis.zcount("fruit", 1.0, 5.0));  
    30.           
    31.         // 查看排名  
    32.         print("zrank fruit grape=" + jedis.zrank("fruit", "grape"));  
    33.         print("zrevrank fruit grape=" + jedis.zrevrank("fruit", "grape"));  
    34.   
    35.         // 按权重排序后读取索引范围内元素及权重  
    36.         System.out.println("zrangeWithScores fruit");  
    37.         Set<Tuple> tuples = jedis.zrangeWithScores("fruit", 0, -1);  
    38.         for (Tuple t : tuples) {  
    39.             System.out.println(t.getElement() + ":" + t.getScore());  
    40.         }  
    41.         System.out.println("------------------------------------------------------");  
    42.         System.out.println();  
    43.   
    44.         // 按权重反向排序后读取索引范围内元素及权重  
    45.         System.out.println("zrevrangeWithScores fruit");  
    46.         tuples = jedis.zrevrangeWithScores("fruit", 0, -1);  
    47.         for (Tuple t : tuples) {  
    48.             System.out.println(t.getElement() + ":" + t.getScore());  
    49.         }  
    50.         System.out.println("------------------------------------------------------");  
    51.         System.out.println();  
    52.   
    53.         // 按权重排序后读取索引范围内元素  
    54.         Set<String> set = jedis.zrange("fruit", 1, 3);  
    55.         print("zrange fruit [1,3]=" + set);  
    56.   
    57.         // 按权重反向排序后读取索引范围内元素  
    58.         set = jedis.zrevrange("fruit", 1, 3);  
    59.         print("zrevrange fruit [1,3]=" + set);  
    60.   
    61.         // 读取权重在指定范围内的元素及其权重并按权重排序  
    62.         System.out.println("zrangeByScoreWithScores fruit [1.0,8.0]");  
    63.         tuples = jedis.zrangeByScoreWithScores("fruit", 1.0, 8.0);  
    64.         for (Tuple t : tuples) {  
    65.             System.out.println(t.getElement() + ":" + t.getScore());  
    66.         }  
    67.         System.out.println("------------------------------------------------------");  
    68.         System.out.println();  
    69.   
    70.         // 读取权重在指定范围内的元素及其权重并按权重反向排序  
    71.         System.out.println("zrevrangeByScoreWithScores fruit [8.0,1.0]");  
    72.         tuples = jedis.zrevrangeByScoreWithScores("fruit", 8.0, 1.0);  
    73.         for (Tuple t : tuples) {  
    74.             System.out.println(t.getElement() + ":" + t.getScore());  
    75.         }  
    76.         System.out.println("------------------------------------------------------");  
    77.         System.out.println();  
    78.   
    79.         // 读取权重在指定范围内的元素并按权重排序  
    80.         set = jedis.zrangeByScore("fruit", 1.0, 7.0);  
    81.         print("zrangeByScore fruit [1.0,7.0]=" + set);  
    82.   
    83.         // 读取权重在指定范围内的元素并按权重反向排序  
    84.         set = jedis.zrevrangeByScore("fruit", 7.0, 1.0);  
    85.         print("zrevrangeByScore fruit [7.0,1.0]=" + set);  
    86.   
    87.         // 查看集合中指定元素的权重  
    88.         double zscore = jedis.zscore("fruit", "grape");  
    89.         print("zscore fruit grape=" + zscore);  
    90.   
    91.         // 修改指定元素权重  
    92.         print("zincrby fruit -2 grape=" + jedis.zincrby("fruit", -2, "grape"));  
    93.         print("zincrby fruit 5.0 lemon=" + jedis.zincrby("fruit", 5.0, "lemon"));  
    94.         print("after zincrby: zscore fruit grape=" + jedis.zscore("fruit", "grape"));  
    95.           
    96.         // 删除元素  
    97.         print("zrem fruit cherry=" + jedis.zrem("fruit", "cherry"));  
    98.         print("zremrangeByScore fruit [3.0,6.0]=" + jedis.zremrangeByScore("fruit", 3.0, 6.0));  
    99.   
    100.         jedis.close();  
    101.     }  
    102.   
    103.     private static void print(String info) {  
    104.         System.out.println(info);  
    105.         System.out.println("------------------------------------------------------");  
    106.         System.out.println();  
    107.     }  
    108. }  

    二、实践练习
    在上一节的基础上,给每个商品增加一个浏览量的记录,商品每次被浏览,设置浏览量加1。

    首先修改添加商品的代码,设置商品的初始浏览量为0。

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * 添加一个商品 
    3.  * @param goods 
    4.  * @return 
    5.  */  
    6. public boolean addGoods(Goods goods) {  
    7.     long id = getIncrementId();  
    8.     Map<String, String> map = new HashMap<>();  
    9.     map.put("id", String.valueOf(id));  
    10.     map.put("title", goods.getTitle());  
    11.     map.put("price", String.valueOf(goods.getPrice()));  
    12.       
    13.     //随机获得三个分类  
    14.     String size = SIZE[new Random().nextInt(SIZE.length)];  
    15.     String color = COLOR[new Random().nextInt(COLOR.length)];  
    16.       
    17.     String key = "goods:" + id;  
    18.     boolean added = jedis.hmset(key, map).equals("OK");  
    19.     if(added) {  
    20.         jedis.rpush("goods:list", String.valueOf(id));  
    21.         //初始浏览量默认为0  
    22.         jedis.zadd("goods:views", 0, String.valueOf(id));  
    23.         //记录商品所属分类  
    24.         jedis.sadd("goods:" + id + ":tags", size, color);  
    25.         //记录每个分类下包含的商品ID  
    26.         jedis.sadd("tag:" + size + ":goods", String.valueOf(id));  
    27.         jedis.sadd("tag:" + color + ":goods", String.valueOf(id));  
    28.     }  
    29.     return added;  
    30. }  

    用户浏览商品方法,浏览量加1。

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * 浏览商品 
    3.  * @param id 
    4.  */  
    5. public void view(long id) {  
    6.     jedis.zincrby("goods:views", 1, String.valueOf(id));  
    7. }  

    按浏览量排序

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * 读取商品列表并按浏览量排序 
    3.  * @param pageIndex 
    4.  * @param pageSize 
    5.  * @return 
    6.  */  
    7. public List<Goods> getGoodsListOrderByViews(int pageIndex, int pageSize) {  
    8.     int totals = (int)getTotalCount();  
    9.     int from = (pageIndex - 1) * pageSize;  
    10.     if(from < 0) {  
    11.         from = 0;  
    12.     }  
    13.     else if(from > totals) {  
    14.         from = (totals / pageSize) * pageSize;  
    15.     }  
    16.     int to = from + pageSize - 1;  
    17.     if(to > totals) {  
    18.         to = totals;  
    19.     }  
    20.     List<Goods> goodsList = new ArrayList<>();  
    21.     Set<String> idList = jedis.zrevrange("goods:views", from, to);  
    22.     for(String id : idList) {  
    23.         String key = "goods:" + id;  
    24.         Map<String, String> maps = jedis.hgetAll(key);  
    25.         Goods goods = new Goods();  
    26.         goods.setId(NumberUtils.toLong(maps.get("id")));  
    27.         goods.setTitle(maps.get("title"));  
    28.         goods.setPrice(NumberUtils.toFloat(maps.get("price")));  
    29.         //读取分类  
    30.         goods.setTags(jedis.smembers("goods:" + id + ":tags"));  
    31.         goodsList.add(goods);  
    32.     }  
    33.     return goodsList;  
    34. }  

    测试代码

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. public static void main(String[] args) {  
    2.     SortedSetLession sl = new SortedSetLession();  
    3.     sl.clear();  
    4.       
    5.     //添加一批商品  
    6.     for(int i = 0; i< 42; i++) {  
    7.         Goods goods = new Goods(0, "goods" + String.format("%05d", (i + 1)), i);  
    8.         sl.addGoods(goods);  
    9.     }  
    10.     //读取商品总数  
    11.     System.out.println("商品总数: " + sl.getTotalCount());  
    12.     //删除第29件商品  
    13.     sl.delGoods(29);  
    14.     System.out.println("删除后商品总数: " + sl.getTotalCount());  
    15.     //分页显示  
    16.     List<Goods> list = sl.getGoodsList(2, 20);  
    17.     System.out.println("第二页商品:");  
    18.     for(Goods goods : list) {  
    19.         System.out.println(goods);  
    20.     }  
    21.     //按分类查找  
    22.     List<Goods> listByTag = sl.findGoodsByTag("big", "green");  
    23.     System.out.println("所有尺寸为big,颜色为green的商品:");  
    24.     for(Goods goods : listByTag) {  
    25.         System.out.println(goods);  
    26.     }  
    27.     //模拟点击商品  
    28.     sl.view(3);  
    29.     sl.view(3);  
    30.     sl.view(4);  
    31.     //按点击量排序  
    32.     List<Goods> listWithOrder = sl.getGoodsListOrderByViews(1, 20);  
    33.     System.out.println("按点击量排序:");  
    34.     for(Goods goods : listWithOrder) {  
    35.         System.out.println(goods);  
    36.     }  
    37. }  

    源码下载

  • 相关阅读:
    lintcode:落单的数
    lintcode: 翻转链表
    lintcode :Reverse Words in a String 翻转字符串
    lintcode :Invert Binary Tree 翻转二叉树
    lintcode : 空格替换
    lintcode:Matrix Zigzag Traversal 矩阵的之字型遍历
    lintcode: 爬楼梯
    lintcode:Compare Strings 比较字符串
    lintcode: 有效的括号序列
    lintcode :Valid Palindrome 有效回文串
  • 原文地址:https://www.cnblogs.com/sa-dan/p/6836894.html
Copyright © 2011-2022 走看看