场景说明

今天我们来模拟一个这样的场景,我们在本地有多个文本文件,每个文件里面存了很多的32位的字符串作为用户的唯一标识,每个用户存做一行,假如我们每天都有非常大规模的用户,这样我们可能在工作中就存在需要对这些用户进行交集、并集或补集等处理,最简单的方式是通过Java中的集合来进行运算即可,比如通过HashSet来进行相应的一些运算,但是这样的运算存在一个局限性,那就是我们一般在JVM运行过程中初始的内存是有限的,这样如果全部在JVM内存中进行计算的话,很容易出现内存空间不足导致的OOM异常,那么我们今天来介绍一种拓展性更强的方式来进行这样的一些交并补的运算:通过Redis来实现数据的交集、并集、补集


环境说明

  • Redis版本: Redis 6.0.6

  • Jedis版本: 4.2.2

  • 工具类hutool版本: 5.8.0.M3

  • pom文件:


<dependencies><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.2.2</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.0.M3</version></dependency></dependencies>

交并补计算


初始化常量


public class RedisCalculateUtils {static String oneFileString = "/Users/tmp/test-1.txt";static String twoFileString = "/Users/tmp/test-2.txt";static String diffFileString = "/Users/tmp/diff-test.txt";static String interFileString = "/Users/tmp/inter-test.txt";static String unionFileString = "/Users/tmp/union-test.txt";static String oneFileCacheKey = "oneFile";static String twoFileCacheKey = "twoFile";static String diffFileCacheKey = "diffFile";static String interFileCacheKey = "interFile";static String unionFileCacheKey = "unionFile";}

初始化数据到指定文件

/**
* 初始化数据并写入文件中
*/
public static void writeFile() {File oneFile = new File(oneFileString);List<String> fs = new ArrayList<>(10000);for (int i = 10000; i < 15000; i++) {String s = SecureUtil.md5(String.valueOf(i));fs.add(s);}FileUtil.writeUtf8Lines(fs, oneFile);File twoFile = new File(twoFileString);fs.clear();for (int i = 12000; i < 20000; i++) {String s = SecureUtil.md5(String.valueOf(i));fs.add(s);}FileUtil.writeUtf8Lines(fs, twoFile);}

指定文件写入Redis


/**
* 读取文件数据并写入Redis
*/
public static void writeCache() {try(Jedis jedis = new Jedis("127.0.0.1", 6379)) {Pipeline p = jedis.pipelined();List<String> oneFileStringList = FileUtil.readLines(oneFileString, "UTF-8");for (String s : oneFileStringList) {p.sadd(oneFileCacheKey, s);}p.sync();List<String> twoFileStringList = FileUtil.readLines(twoFileString, "UTF-8");for (String s : twoFileStringList) {p.sadd(twoFileCacheKey, s);}p.sync();} catch (Exception e) {throw new RuntimeException(e);}
}

差集的计算

/*** oneKey对应的Set 与 twoKey对应的Set 的差集 并写入 threeKey* @param oneKey 差集前面的集合Key* @param twoKey 差集后面的集合Key* @param threeKey 差集结果的集合Key*/public static void diff(String oneKey, String twoKey, String threeKey) {try(Jedis jedis = new Jedis("127.0.0.1", 6379)) {long result = jedis.sdiffstore(threeKey, oneKey, twoKey);System.out.println("oneKey 与 twoKey 的差集的个数:" + result);} catch (Exception e) {throw new RuntimeException(e);}}

差集计算结果写入到指定文件

/*** 将计算的差集数据写入到指定文件*/public static void writeDiffToFile() {File diffFile = new File(diffFileString);try(Jedis jedis = new Jedis("127.0.0.1", 6379)) {Set<String> result = jedis.smembers(diffFileCacheKey);FileUtil.writeUtf8Lines(result, diffFile);} catch (Exception e) {throw new RuntimeException(e);}}

交集的计算


/**** @param cacheKeyArray 交集集合Key* @param destinationKey 交集集合结果Key*/public static void inter(String[] cacheKeyArray, String destinationKey) {try(Jedis jedis = new Jedis("127.0.0.1", 6379)) {long result = jedis.sinterstore(destinationKey, cacheKeyArray);System.out.println("cacheKeyArray 的交集的个数:" + result);} catch (Exception e) {throw new RuntimeException(e);}}

交集计算结果写入指定文件

/*** 将计算的交集数据写入到指定文件*/public static void writeInterToFile() {File interFile = new File(interFileString);try(Jedis jedis = new Jedis("127.0.0.1", 6379)) {Set<String> result = jedis.smembers(interFileCacheKey);FileUtil.writeUtf8Lines(result, interFile);} catch (Exception e) {throw new RuntimeException(e);}}

并集的计算

/*** 计算多个Key的并集并写入到新的Key* @param cacheKeyArray 求并集的Key* @param destinationKey 并集结果写入的KEY*/public static void union(String[] cacheKeyArray, String destinationKey) {try(Jedis jedis = new Jedis("127.0.0.1", 6379)) {long result = jedis.sunionstore(destinationKey, cacheKeyArray);System.out.println("cacheKeyArray 的并集的个数:" + result);} catch (Exception e) {throw new RuntimeException(e);}}

并集计算结果写入到指定文件

/*** 将计算的并集数据写入到指定文件*/public static void writeUnionToFile() {File unionFile = new File(unionFileString);try(Jedis jedis = new Jedis("127.0.0.1", 6379)) {Set<String> result = jedis.smembers(unionFileCacheKey);FileUtil.writeUtf8Lines(result, unionFile);} catch (Exception e) {throw new RuntimeException(e);}}

Redis命令说明


SDIFFSTORE destination key [key …]

举例说明:

key1 = {a,b,c,d}
key2 = {c}
key3 = {a,c,e}
SDIFF key1 key2 key3 = {b,d}

SDIFFSTORE 命令的作用和SDIFF类似,不同的是它将结果保存到 destination 集合,而把结果集返回给客户端。

如果 destination 集合已经存在,则将其覆盖。

  • 返回值
    结果集中成员数量

SINTERSTORE destination key [key …]

举例说明:

key1 = {a,b,c,d}
key2 = {c}
key3 = {a,c,e}
SINTER key1 key2 key3 = {c}

SINTERSTORE 命令与 SINTER 命令类似,不同的是它并不是直接返回结果集,而是将结果保存在 destination 集合中。

如果 destination 集合存在, 则会被覆盖。

  • 返回值
    结果集中成员数量

SUNIONSTORE destination key [key …]

举例说明:

key1 = {a,b,c,d}
key2 = {c}
key3 = {a,c,e}
SUNION key1 key2 key3 = {a,b,c,d,e}

SUNIONSTORE 命令的功能类似于 SUNION,不同的是不反回结果集,而是存储在 destination 中。

如果 destination 已经存在,则被覆盖。

  • 返回值
    结果集中的成员数量

参考资料: https://www.redis.com.cn/set.html

通过Redis实现数据的交集、并集、补集相关推荐

  1. 集合中常用的合并 求交集 并集 补集问题

    1.在平时的时候经常会用到求交集.补集.并集.差集的问题 本文通过引入org.apache.commons.collections4.CollectionUtils 进行很方便的解决 ArrayLis ...

  2. oracle表交集并集,Oracle 取两个表中数据的交集并集差异集合

    Oracle 作为一个大型的关系数据库,日常应用中往往需要提取两个表的交集数据 例如现有如下表,要求找出工资2500(不含2500)以上并且是男性(M)的员工编号,那么就要利用这两个表的关系做一个交集 ...

  3. oracle关联查询取交集,Oracle 取两个表中数据的交集并集差异集合

    Oracle 作为一个大型的关系数据库,日常应用中往往需要提取两个表的交集数据 例如现有如下表,要求找出工资2500(不含2500)以上并且是男性(M)的员工编号,那么就要利用这两个表的关系做一个交集 ...

  4. oracle 多个表取并集,Oracle?取两个表中数据的交集并集差异集合

    Oracle 作为一个大型的关系数据库,日常应用中往往需要提取两个表的交集数据 例如现有如下表,要求找出工资2500(不含2500)以上并且是男性(M)的员工编号,那么就要利用这两个表的关系做一个交集 ...

  5. Python绘制韦恩图并通过集合找到交集并集数据

    matplotlib_venn库里支持venn2和venn3,以venn3为例绘图: venn中包含venn2-venn6,以venn4为例绘图. 安装库:pip install matplotlib ...

  6. redis lettuce 超时_Spring Cache 操作 Redis 实现数据缓存(上)

    点击上方☝SpringForAll社区 轻松关注!及时获取有趣有料的技术文章 本文来源:http://www.mydlq.club/article/55/ . 一.缓存概念知识 . 1.是什么缓存 . ...

  7. SpringBoot 结合 Spring Cache 操作 Redis 实现数据缓存

    点击上方"后端技术精选",选择"置顶公众号" 技术文章第一时间送达! 作者:超级小豆丁 http://www.mydlq.club/article/55/ 系统 ...

  8. redis 热点数据 缓存

    Redis 是什么 Redis 的五种基本类型 STRING LIST SET HASH ZSET 键的过期时间 发布与订阅 事务 持久化 快照持久化 AOF 持久化 复制 从服务器连接主服务器的过程 ...

  9. spring + redis 实现数据的缓存

    1.实现目标 通过redis缓存数据.(目的不是加快查询的速度,而是减少数据库的负担) 2.所需jar包 注意:jdies和commons-pool两个jar的版本是有对应关系的,注意引入jar包是要 ...

  10. go自定义和使用set包处理列表 交集 并集 差集

    自定义交集 并集 差集 package mainimport "fmt"func main() {aList := []string{"1", "2& ...

最新文章

  1. linux截图快捷键
  2. 框架学习与探究之AOP--Castle DynamicProxy
  3. Oracle中CHAR类型不足位数时,用空格自动补足位数
  4. 黄章钦点的魅族大将,为什么会引发群嘲?
  5. 比较Apache Hadoop 生态系统中不同的文件格式和存储引擎的性能
  6. Java 核心系列教程
  7. IPSEC 001 --- 原理简介
  8. 42表盘直径是从哪测量_万用表测量电容容量的方
  9. mac配置VMware Fusion虚拟机网络配置
  10. 微信小程序input输入框控制金额格式
  11. 计算机中数据的计量单位
  12. Python自学(三)
  13. 莫国防病毒(win32.mgf)源代码
  14. android 自定义viewpager指示器,Android自定义View Flyme6的Viewpager指示器
  15. 颠覆平庸:在技术上持续精进
  16. Linux 系统调用的本质
  17. 编程. 已知字符串:this is a test of java. 按要求执行以下操作: (1) 统计该字符串中字母s出现的次数 (2) 取出子字符串test (3) 用多种方式将本字
  18. 数据库系统的基本概念
  19. 当使用maven的clear功能导致数据库链接出现Using a password on the command line interface can be insecure.的解决方案
  20. 湖南评副教授职称计算机,2019年职称评审,湖南省高校教师需关注这些问题!...

热门文章

  1. 3V转1.8V三极管稳压IC
  2. MaxCompute SQL
  3. 引用arXiv的文章标准的Latex的bib如何编辑
  4. 泰坦尼克号数据_数据分析实战3:泰坦尼克号生存分析
  5. 1984-1999:中国电影的黄金十五年
  6. 公众号搜题怎么实现的?
  7. 2020年的5种常见骇客行为,你的电脑安全吗?
  8. Python的pyhanlp库使用(自然语言识别、姓名)
  9. 生于七十年代的20位最具潜质商业精英
  10. commonAncestor