栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

通过Redis实现数据的交集、并集、补集

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

通过Redis实现数据的交集、并集、补集

场景说明

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


环境说明
  • Redis版本: Redis 6.0.6

  • Jedis版本: 4.2.2

  • 工具类hutool版本: 5.8.0.M3

  • pom文件:


        
            redis.clients
            jedis
            4.2.2
        

        
            cn.hutool
            hutool-all
            5.8.0.M3
        


    

交并补计算
初始化常量
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 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

public static void writeCache() {
    try(Jedis jedis = new Jedis("127.0.0.1", 6379)) {
        Pipeline p = jedis.pipelined();
        List oneFileStringList = FileUtil.readLines(oneFileString, "UTF-8");

        for (String s : oneFileStringList) {
            p.sadd(oneFileCacheKey, s);
        }
        p.sync();

        List twoFileStringList = FileUtil.readLines(twoFileString, "UTF-8");

        for (String s : twoFileStringList) {
            p.sadd(twoFileCacheKey, s);
        }
        p.sync();

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

差集的计算
    
    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 result = jedis.smembers(diffFileCacheKey);
            FileUtil.writeUtf8Lines(result, diffFile);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    

交集的计算

    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 result = jedis.smembers(interFileCacheKey);
            FileUtil.writeUtf8Lines(result, interFile);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    

并集的计算
    
     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 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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/887440.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号