共计 5072 个字符,预计需要花费 13 分钟才能阅读完成。
本篇内容介绍了“Redis 如何实现数据的交集、并集和补集”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
场景说明
今天我们来模拟一个这样的场景,我们在本地有多个文本文件,每个文件里面存了很多的 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 已经存在,则被覆盖。
返回值
结果集中的成员数量
“Redis 如何实现数据的交集、并集和补集”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!