共計 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 小編將為大家輸出更多高質量的實用文章!