高效求两个list的差集

2023-05-16

查一个ListA 的每个值(String字符串)在另外一个ListB中是否存在,如果不存在就记录下来。

 

模拟数据量:100万

 

方法一:

直接调用list自带的removeAll方法

    public static void main(String[] args) throws IOException {
        List<String> listA = new ArrayList();
        List<String> listB = new ArrayList();
        for (int i = 0; i < 1000000; i++) {
            listA.add(UUID.randomUUID().toString().hashCode() + i + "");
        }
        for (int i = 0; i < 1000000; i++) {
            listB.add(i + UUID.randomUUID().toString().hashCode() + "");
        }
        long startTime = System.currentTimeMillis();
        listA.removeAll(listB);
        long endTime = System.currentTimeMillis();

        System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
    }

耗时:好几分钟了都没好,等不下去

原因:

removeAll()内部的实现如下,直接实现暴力遍历的方法:


    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }


再看看方法内部的contains(),也是直接暴力

    public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }

 

方法二(JDK为1.8):

借用HashMap,空间换取时间

    public static void main(String[] args) throws IOException {
        List<String> listA = new ArrayList();
        List<String> listB = new ArrayList();
        for (int i = 0; i < 1000000; i++) {
            listA.add(UUID.randomUUID().toString().hashCode() + i + "");
        }
        for (int i = 0; i < 1000000; i++) {
            listB.add(i + UUID.randomUUID().toString().hashCode() + "");
        }
        long startTime = System.currentTimeMillis();
        HashMap<String, Boolean> map = new HashMap();
        for (int i = 0; i < 1000000; i++) {
            map.put(listA.get(i), true);
        }
        listA.clear();
        for (int i = 0; i < 1000000; i++) {
            String x = listB.get(i);
            if (!map.containsKey(x)) {
                listA.add(x);
            }
        }
        long endTime = System.currentTimeMillis();

        System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
    }

耗时:535ms,1秒不到。

分析:

与方法一不同的地方是,我们借用了HashMap(JDK1.8),为什么要用HashMap,
其实是因为HashMap的containsKey方法,JDK1.8后它引入了红黑树,优化了查找速度(查找时间复杂度为 O(logn))。


其实现如下

    public boolean containsKey(Object key) {
        return getNode(hash(key), key) != null;
    }

    final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
            if ((e = first.next) != null) {
                if (first instanceof TreeNode)
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
    }

了解:HashMap 在 JDK 1.8 后新增的红黑树结构

          JDK1.7中HashMap底层实现原理

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高效求两个list的差集 的相关文章

  • 使用 Linq 返回具有最大计数的列表

    使用 C 和 Linq 如何返回具有最大大小 计数的 List 我假设您有一个名为的列表集合lists并且您想要返回此集合中元素最多的列表 如果是这样 请尝试以下操作 var listWithLargestCount lists Order
  • 如何在 Haskell 中向右或向左移动列表的 1 个元素?

    嗨 我一直在寻找答案 但找不到 假设我们有一个像这样的列表 1 10 4 5 3 我怎样才能将 5 向左移动 使这个列表变成 1 10 5 4 3 我尝试过了swapElementsAt通过找到该元素的索引 但它看起来非常不足 swapEl
  • Python 3 中的递归搜索 JSON/DICT

    我在 Python 3 中实现了一些 API 这些 API 允许我根据班级代码接收有关学校的信息 但我想知道如何通过类代码获取信息 例子 我输入代码GF528S我希望程序告诉我班级 3C INF 地址 Address 1 Milan 如果可
  • 检查子字符串是否在字符串列表中?

    我之前已经找到了这个问题的一些答案 但它们对于当前的Python版本来说似乎已经过时了 或者至少它们对我不起作用 我想检查字符串列表中是否包含子字符串 我只需要布尔结果 我找到了这个解决方案 word to check or wordlis
  • Django查询:如何过滤对象以排除列表中的id?

    如何在查询中进行过滤 以便结果排除 ID 属于列表的任何对象实例 可以说我有 object id list 1 5 345 MyObject objects filter Q time gte datetime now Q what to
  • Backbone Marionette CompositeView 排序列表 - 在添加时呈现额外的模型

    这是小提琴 http jsfiddle net QhQ8D 10 http jsfiddle net QhQ8D 10 代码在下面 制作一个聊天应用程序 需要一个排序的 连接的用户列表 名称上带有比较器的图形集合连接到 CompositeV
  • 查找列表中项目的索引

    给定一个列表 foo bar baz 和列表中的一个项目 bar 如何获取它的索引1 gt gt gt foo bar baz index bar 1 See 文档 https docs python org tutorial datast
  • 迭代列表的奇怪速度差异

    我创建了两个重复两个不同值的长列表 在第一个列表中 值交替出现 在第二个列表中 一个值出现在另一个值之前 a1 object object 10 6 a2 a1 2 a1 1 2 然后我迭代它们 不对它们执行任何操作 for in a1 p
  • Scala 中的随机列表[重复]

    这个问题在这里已经有答案了 我对 scala 中的随机播放列表有疑问 使用scala util Random 例如我有 val a cyan val b magenta val c yellow val d key val color Ra
  • C# List 内部结构

    将对象添加到集合 例如 List 时到底会发生什么 List
  • 当顺序很重要时如何从元组列表中删除重复项

    我看过一些类似的答案 但我找不到针对这种情况的具体内容 我有一个元组列表 5 0 3 1 3 2 5 3 6 4 我想要的是仅当元组的第一个元素先前出现在列表中并且剩余的元组应该具有最小的第二个元素时 才从该列表中删除元组 所以输出应该是这
  • 在 R 中提取 data.frames 列表的名称以及 data.frame 中的值

    在下面的代码中 j是 data frames 的命名列表 我想知道是否有办法 a 提取变量的数值 即one short and one long 在 data frames 内并附加它们的相关名称 即 AAA or BBB or CCC 到
  • php如何生成动态list()?

    根据我的理解 这就是 list 的工作原理 list A1 A2 A3 array B1 B2 B3 所以在帮助下list 我们可以相应地从数组中分配值 这是我的问题 如何生成动态list 1 基于数据库返回结果 我不确定有多少 但我将其全
  • Python:如何在不先创建整个列表的情况下计算列表的总和?

    通常我们必须 1 声明一个列表 2 使用以下方法计算该列表的总和sum 但现在我希望指定一个以 1 开头 间隔为 4 100 个元素的列表 如下所示 1 5 9 13 17 21 25 29 33 37 我不想涉及数学公式 所以 1 如何在
  • python中有没有一种方法可以将存储在列表中的正则表达式模式列表应用到单个字符串?

    我有一个正则表达式模式列表 存储在列表类型中 我想将其应用于字符串 有谁知道一个好方法 将列表中的每个正则表达式模式应用于字符串 和 如果匹配 则调用与列表中该模式关联的不同函数 如果可能的话我想用 python 来做这件事 提前致谢 im
  • 如何将嵌套列表切片两次?

    使用嵌套列表 例如 ex list 1 2 3 4 5 6 7 8 9 我需要能够将此列表分割为 1 2 4 5 我一直在尝试 list ex list 2 2 但这不起作用 我显然做了一些非常错误的事情 但一直无法找到解决方案 因为由于某
  • 如何设置行高 Sencha Touch List

    如何设置 Sencha Touch List 对象中的行高 我使用 HTML 来格式化行 多行行会变得更高 但如何设置行高 谢谢 格里 要编辑列表元素的默认高度 有两种方法 使用 SASS 创建您自己的 Sencha 主题 官方 Sench
  • 将非常大的Python列表输出保存到mysql表中

    我想将 python 生成的列表的输出保存在 mysql 数据库的表中 该表如下所示 mysql 中的 myapc8 表 https i stack imgur com 4B4Hz png这是Python代码 在此输入图像描述 https
  • 给定一个排序数组,就地删除重复项,使每个元素仅出现一次并返回新长度

    完整的问题 我开始在线学习 python 但对这个标记为简单的问题有疑问 给定一个排序数组 就地删除重复项 使得每个 元素只出现一次并返回新的长度 不分配 另一个数组的额外空间 您必须通过修改输入来完成此操作 数组就地 具有 O 1 额外内
  • 如何使用foldr为列表创建显示实例?

    我想为我的数据类型 我的列表 编写自己的显示实例 到目前为止 我的方法是有效的 但我总是在末尾有一个逗号 我已经尝试用最后一个元素启动折叠并将其从列表中删除 但它很麻烦而且不起作用 有没有更简单的方法来获得正确的解决方案 实际 1 2 3

随机推荐

  • Linux命令行卡住不显示命令的解决方法

    1 问题描述 在使用终端工具如Xshell iTerm2时登录到linux服务器后 xff0c 在运行某些程序出错时 xff0c 有的时候会出现命令行卡住不显示命令的情况 2 解决方案 在命令行中输入reset xff0c 再回车即可 xf
  • word文档转换为md文档

    1 xff0c 安装软件 官网 xff1a Pandoc Installing pandoc 2 xff0c 打开cmd xff0c 切换到word文件所在的目录 这个不会可以自行百度不难 3 xff0c 在根文件目录下输入如下这行代码 p
  • docker 的 --rm与docker rm 的区别

    Dockerfile里的VOLUME和docker run v path的时候挂载容器的挂载点效果是一致的 会在宿主机 var lib docker volumes目录生成随机目录 发现 rm不单单是删除掉容器 xff0c 还会删掉挂载点的
  • jenkins 面试题

    1 jenkins是什么 Jenkins是一个开源的 可扩展的持续集成 交付 部署 xff08 软件 代码的编译 打包 部署 xff09 的基于web界面的平台 允许持续集成和持续交付项目 xff0c 无论用的是什么平台 xff0c 可以处
  • ubuntu18.04安装llvm-9 clang-9

    低版本的ubuntu只能采用编译安装的方式 xff0c 高版本的ubuntu可以采用如下方式安装 span class token keyword echo span deb http apt llvm org xenial llvm to
  • linux 下conda环境的配置

    1 安装 anaconda 3 0 下载安装包 xff1a span class token function wget span https repo continuum io archive Anaconda3 5 0 0 Linux
  • Linux 下如何添加一个普通用户,并给予用户root权限

    1 添加用户 xff0c 首先用adduser命令添加一个普通用户 xff0c 命令如下 adduser test1 添加一个名为tommy的用户 span class token function passwd span test1 修改
  • 不使用密码向github提交代码

    每次向github提交代码时都要输入用户名密码 xff0c 太麻烦了 xff0c 影响效率 解决方法 xff1a 1 在命令行中输入 span class token function git span config global cred
  • centos7系统安装好后远程连接执行命令很卡

    centos7系统安装好后 xff0c 远程连接也ok 但远程连接之后执行命令很卡 xff0c 这个问题可能是macaddr导致的 xff0c 我们要检查一下macaddr是否和其他的服务器相同 MACADDR 61 其中 以AA BB C
  • UESTC 1170 红蓝点对

    UESTC 1170 是个变异的最近点对题目 xff0c 用分治策略和计算几何做的话好像会超因为时间上是1000ms xff0c 下面这个贪心做法是看了别人的博客知道的 处理红点到原点的距离然后根据距离排序 xff0c 蓝点一样 xff0c
  • CDH环境下HDFS权限问题

    CDH环境下Hadoop平台最高权限用户是hdfs xff0c 属于supergroup组 默认HDFS会开启权限认证 xff0c 所以操作时 xff0c 需要将root用户切换到hdfs用户 xff0c 否则会报错 问题 xff1a or
  • 手动开启/关闭HDFS的safemode(安全模式)

    在hadoop启动namenode的时候 xff0c 会启动安全模式 xff08 safemode xff09 xff0c 在该模式下 xff0c namenode会等待datanode向它发送块报告 xff08 block report
  • centos7 update gcc to 7.2

    centos7默认的gcc版本是4 8 xff0c 我们需要升级到7 2 安装gcc span class token function wget span https github com gcc mirror gcc archive r
  • centos7升级GLIBC后导致系统不能启动成功

    centos7 glibc2 13 glibc2 27 1 准备U盘系统盘 xff0c 系统要和原来的系统版本匹配 开机重启按F2进入BIOS xff0c 通过U盘启动系统 选择Rescue mode 2 接下来 xff0c 选择 Resc
  • 在Linux中如何运行C语言写的脚本

    目录 1 xff1a Linux下如何运行C语言脚本 2 xff1a 实例展示 1 xff1a Linux下如何运行C语言脚本 Linux别的系统我不知道是不是这个方法 xff0c 我是用的ubuntu的 xff0c 其他的我也没测试过 x
  • Linux——利用Shell脚本编写进度条

    初级版本 xff08 原始进度条 xff09 xff1a span class hljs shebang bin bash span span class hljs built in echo span span class hljs st
  • C语言的日期和时间函数的用法及相应示例

    1 xff0e 概念 在C C 43 43 中 xff0c 对字符串的操作有很多值得注意的问题 xff0c 同样 xff0c C C 43 43 对时间的操作也有许多值得大家注意的地方 下面主要介绍在C C 43 43 中时间和日期的使用方
  • xrdp完美实现Windows远程访问Ubuntu 16.04【包括多人桌面与原生桌面】

    多人桌面 1 安装xrdp sudo apt get install xrdp 2 安装vnc4server 我这里是安装xrdp的时候自动安装的 我看网上很多说是需要单独安装的 3 安装xfce4 sudo apt get install
  • C++ range

    C 43 43 20 引入了 range 来简化对元素序列的处理 xff08 可以省略掉许多的循环遍历 xff09 1 range 和 view range range concept 通过提供一个迭代器以及一个哨兵来表示一个元素范围 xf
  • 高效求两个list的差集

    查一个ListA 的每个值 xff08 String字符串 xff09 在另外一个ListB中是否存在 xff0c 如果不存在就记录下来 模拟数据量 xff1a 100万 方法一 xff1a 直接调用list自带的removeAll方法 p