Redis集合类型的基础功能也是存储字符串列表,和列表类型的区别是字符串不能重复且没有顺序。当然,存储元素唯一性也可以通过应用程序保证,单从这一点上并没有体现出对比列表类型的特点。

其实,集合类型的一个鲜明特性是可以对多个集合求交集、并集和差集。例如在一个社交应用中,A用户有C、D两个好友,B用户有D、E两个好友,可用通过sinter A B的命令很方便的查出A和B的共同好友。

本节中将利用这个特性给实践练习中的商品管理模块添加一个按分类查找商品的功能。

一、常用命令

import java.util.Set;

import redis.clients.jedis.Jedis;

public class SetExample {

	public static void main(String[] args) {
Jedis jedis = JedisProvider.getJedis();
jedis.flushDB(); // 向sets集合中加入元素, 成功返回1, 失败返回0
Long sadd = jedis.sadd("fruit", "apple");
print("sadd fruit apple=" + sadd); //不能添加重复元素
sadd = jedis.sadd("fruit", "apple");
print("sadd fruit apple again=" + sadd);
jedis.sadd("fruit", "banana", "orange", "grape"); // 返回所有元素
print("smembers fruit=" + jedis.smembers("fruit")); // 删除元素
long srem = jedis.srem("fruit", "apple");
print("srem fruit apple=" + srem); // 判断是否存在元素
boolean exists = jedis.sismember("fruit", "apple");
print("sismember fruit apple=" + exists);
exists = jedis.sismember("fruit", "banana");
print("sismember fruit banana=" + exists); // 统计元素个数
print("scard fruit=" + jedis.scard("fruit")); // 随机获取一个元素
print("srandmember fruit=" + jedis.srandmember("fruit")); // 随机弹出一个元素
print("spop fruit=" + jedis.spop("fruit")); jedis.sadd("fruit", "apple", "banana", "orange", "grape");
jedis.sadd("food", "orange", "grape", "peach", "lemon"); // 求交集
Set<String> set = jedis.sinter("fruit", "food");
print("sinter fruit food=" + set); // 求交集并存储到指定集合
jedis.sinterstore("sinter", "fruit", "food");
print("sinterstore sinter=" + jedis.smembers("sinter")); // 求并集
set = jedis.sunion("fruit", "food");
print("sunion fruit food=" + set); // 求差集(fruit中有, food中没有的元素)
set = jedis.sdiff("fruit", "food");
print("sdiff fruit food=" + set); jedis.close();
} private static void print(String info) {
System.out.println(info);
System.out.println("------------------------------------------------------");
System.out.println();
}
}

二、实践练习

首先修改商品类,添加一个设置分类的属性 Goods.java

	private Set<String> tags;
public Set<String> getTags() {
return tags;
}
public void setTags(Set<String> tags) {
this.tags = tags;
}

然后给商品管理类添加两个字符串数组用于随机获得分类

	private final String[] SIZE = { "small", "middle", "big" };
private final String[] COLOR = { "red", "yellow", "green" };

修改添加商品的方法,同时保存分类信息

	/**
* 添加一个商品
* @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 size = SIZE[new Random().nextInt(SIZE.length)];
String color = COLOR[new Random().nextInt(COLOR.length)]; String key = "goods:" + id;
boolean added = jedis.hmset(key, map).equals("OK");
if(added) {
jedis.rpush("goods:list", String.valueOf(id));
//记录商品所属分类
jedis.sadd("goods:" + id + ":tags", size, color);
//记录每个分类下包含的商品ID
jedis.sadd("tag:" + size + ":goods", String.valueOf(id));
jedis.sadd("tag:" + color + ":goods", String.valueOf(id));
}
return added;
}

按分类查找商品

	/**
* 查找指定尺寸和颜色的商品
* @param size
* @param color
* @return
*/
public List<Goods> findGoodsByTag(String size, String color) {
Set<String> ids = jedis.sinter("tag:" + size + ":goods", "tag:" + color + ":goods");
List<Goods> goodsList = new ArrayList<>();
for(String id : ids) {
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")));
//读取分类
goods.setTags(jedis.smembers("goods:" + id + ":tags"));
goodsList.add(goods);
}
return goodsList;
}

测试代码

	public static void main(String[] args) {
SetLession sl = new SetLession();
sl.clear(); //添加一批商品
for(int i = 0; i< 42; i++) {
Goods goods = new Goods(0, "goods" + String.format("%05d", (i + 1)), i);
sl.addGoods(goods);
}
//读取商品总数
System.out.println("商品总数: " + sl.getTotalCount());
//删除第29件商品
sl.delGoods(29);
System.out.println("删除后商品总数: " + sl.getTotalCount());
//分页显示
List<Goods> list = sl.getGoodsList(2, 20);
System.out.println("第二页商品:");
for(Goods goods : list) {
System.out.println(goods);
}
//按分类查找
List<Goods> listByTag = sl.findGoodsByTag("big", "green");
System.out.println("所有尺寸为big,颜色为green的商品:");
for(Goods goods : listByTag) {
System.out.println(goods);
}
}

源码下载

Redis从基础命令到实战之集合类型(Set)的更多相关文章

  1. Redis从基础命令到实战之列表类型(List)

    经过上一篇基于Redis散列类型的改造后,实战练习中的商品管理已经具备了增加.修改整体.修改部分属性和分页查询功能,但仍然不支持删除商品的功能.这是因为商品总数是以一个自增数字记录的,且关联了新商品k ...

  2. Redis从基础命令到实战之字符串类型

    字符串类型是Redis中最基本的数据类型,能存储任何形式的字符串和和二进制数据.本文以代码形式列举常用的操作命令,并在实践部分演示一个简单的商品管理功能,实现了通常使用关系型数据库开发的增改查功能,注 ...

  3. Redis从基础命令到实战之有序集合类型(SortedSet)

    有序集合类型是Redis五种数据类型中最高级的.也是最复杂的类型.有序集合具有集合类型的特性,在其基础上给每个元素关联了一个分值,或称为权重,操作时既可以在添加元素时指定分值,也可以单独修改集合中某一 ...

  4. Redis从基础命令到实战之散列类型(Hash)

    从上一篇的实例中可以看出,用字符串类型存储对象有一些不足,在存储/读取时需要进行序列化/反序列化,即时只想修改一项内容,如价格,也必须修改整个键值.不仅增大开发的复杂度,也增加了不必要的性能开销. 一 ...

  5. Redis常用命令入门4:集合类型

    集合类型 之前我们已经介绍过了最基本的字符串类型.散列类型.列表类型,下面我们一起学习一下集合类型. 集合类型也是体现redis一个比较高价值的一个类型了.因为Redis的集合类型,所以我们可以很容易 ...

  6. redis之基础命令

    一.redis介绍 1.redis特性 Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件 redis是c语言编写的,支持数据持久化,是key-val ...

  7. redis的基础命令操作

    文章目录 前言 一.字符串类型 二.哈希类型 三.列表类型 四.集合类型 五.有序集合类型 六.通过命令 前言 redis的数据结构 redis存储的是key,value格式的数据,其中的key是字符 ...

  8. Redis自学笔记:3.6入门-有序集合类型

    3.6有序集合类型 3.6.1介绍 在集合类型基础上,为集合中每个元素都关联了一个分数,故可以获得 分数最高(最低)的前N个元素,可以获得指定范围内的元素等 有序集合中每个元素不同,但它们的分数却可以 ...

  9. 2015/9/4 Python基础(8):映射和集合类型

    Python里唯一的映射类型是字典.映射类型对象里,hash值(key)和指向的对象(值)是一对多的关系.字典对象是可变的,这一点上很像列表,它也可以存储任意个数任意类型的Python对象,其中包括容 ...

随机推荐

  1. Spark Job的提交与task本地化分析(源码阅读八)

    我们又都知道,Spark中任务的处理也要考虑数据的本地性(locality),Spark目前支持PROCESS_LOCAL(本地进程).NODE_LOCAL(本地节点).NODE_PREF.RACK_ ...

  2. dependencies 和 devDependencies

    npm install node_module –save自动更新dependencies字段值 npm install node_module –save-dev自动更新devDependencie ...

  3. 彻底解决rman恢复碰到ora-01152错

    说说碰到这个问题的背景.使用NBU调脚本对oracle进行备份.脚本如下:RUN {ALLOCATE CHANNEL ch00 TYPE 'SBT_TAPE';ALLOCATE CHANNEL ch0 ...

  4. Programming in Lua读书笔记

         Lua的长处之一就是可以通过新类型和函数来扩展其功能.动态类型检查最大限度允许多态出现,并自动简化调用内存管理的接口,因为这样不需要关心谁来分配内存谁来释放内存,也不必担心数据溢出.高级函数 ...

  5. Webpack 入门指南 - 2.模块

    这一次我们谈谈模块问题. 通常我们希望这个项目可以分为多个独立的模块,比如,上一次提高的 hello 函数,如果我们定义为一个模块,其它模块引用之后,直接调用就好了.在前端怎么使用模块呢?这可说来话长 ...

  6. how to enable remote access for root user

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

  7. OpenSSL漏洞补救办法详解(转)

    CVE-2014-0160漏洞背景 2014年4月7日OpenSSL发布了安全公告,在OpenSSL1.0.1版本中存在严重漏洞(CVE-2014-0160).OpenSSL Heartbleed模块 ...

  8. mysql连接查询,封装mysql函数

    连接查询 交叉连接语法: select  * | 字段列表 from 表1  cross join 表2 内连接: select *|字段列表 from 左表 inner join 右表 on 左表. ...

  9. onethink入门笔记(二)

    5.onethink页面端获得后台服务器传值的方法 1:一般后台通过assign的值前台通过{$value}显示出来; 2:如果需要在js中使用 则可以通过 在js中写 var m = "{ ...

  10. STL之序列容器vector

    首先来看看vector的模板声明: template <class T, class Alloc = allocator<T>> class vector { //… }; v ...