快速从2个List集合中找出相同/不同元素

最近刚好涉及到从2个不同集合中找出不同的元素的需求,以下为测试代码

1、利用 apache collection 工具内中的方法,附上坐标

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>

collection 工具包中给出出了2个比较方便的工具方法

1、找共同的元素 org.apache.commons.collections.ListUtils.retainAll(Collection, Collection) 附上源码如下

    public static List removeAll(Collection collection, Collection remove) {
        List list = new ArrayList();
        for (Iterator iter = collection.iterator(); iter.hasNext();) {
            Object obj = iter.next();
            if (remove.contains(obj) == false) {
                list.add(obj);
            }
        }
        return list;
    }

2、找出不同的元素 org.apache.commons.collections.ListUtils.removeAll(Collection, Collection) 附上源码如下

    public static List retainAll(Collection collection, Collection retain) {
        List list = new ArrayList(Math.min(collection.size(), retain.size()));

        for (Iterator iter = collection.iterator(); iter.hasNext();) {
            Object obj = iter.next();
            if (retain.contains(obj)) {
                list.add(obj);
            }
        }
        return list;
    }

附上测试 demo 代码

    public static void main(String[] args) {
        // 生成集合1
        List<Integer> list1 = Lists.newArrayList();
        for (int i = 0; i < 100000; i++) {
            list1.add(i);
        }
        // 生成集合 2
        List<Integer> list2 = Lists.newArrayList();
        for (int i = 0; i < 100001; i++) {
            list2.add(i);
        }
        long start = System.currentTimeMillis();
        // 开始分离
        List<Integer> list = ListUtils.removeAll(list2, list1);
        long end = System.currentTimeMillis();
        System.out.println(list);
        System.out.println(end - start);
        // 总执行次数 100000*100001
    }

执行结果如下

[100000]
4027

通过源码可以看出 集合迭代过程执行了100000*100001 次,随着数据量增加,速度将越来越慢,所以有了如下的优化方案, 付上代码

    public static void main(String[] args) {
        // 生成集合1
        List<Integer> list1 = Lists.newArrayList();
        for (int i = 0; i < 100000; i++) {
            list1.add(i);
        }
        // 生成集合2
        List<Integer> list2 = Lists.newArrayList();
        for (int i = 0; i < 100001; i++) {
            list2.add(i);
        }
        long start = System.currentTimeMillis();
        //开始分离
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (Integer integer : list2) {
            map.put(integer, 1);
        }
        for (Integer integer : list1) {
            map.put(integer, 2);
        }
        List<Integer> list3 = new ArrayList<Integer>();
        Set<Entry<Integer, Integer>> entrySet = map.entrySet();
        for (Entry<Integer, Integer> entry : entrySet) {
            Integer value = entry.getValue();
            if (Objects.equals(1, value)) {
                list3.add(entry.getKey());
            }
        }
        //结束分离
        long end = System.currentTimeMillis();
        System.out.println(list3);
        System.out.println(end - start);
        //总执行次数 100000+100001+100001
    }

执行结果

[100000]
33

差距非常明显,且我们分析执行次数可以看出,通过map执行迭代次数为100000+100001+100001 迭代次数减少很多,速度自然上来了

总结:当数据量不大的情况下,通过ListUtils.removeAll 的方式还是非常推荐,毕竟不用自己造轮子,但是如果数据量达到百万级以上时,推荐使用Map的方式

原文地址:https://www.cnblogs.com/zhanh247/p/12109114.html

时间: 2024-07-29 10:55:31

快速从2个List集合中找出相同/不同元素的相关文章

C语言 选择排序算法原理和实现 从数组中 找出最小的元素然后交换位置

#include <stdio.h> int main(void) { /* 选择排序算法 原理:从数组中 找出最小的元素然后交换位置: */ int a[10] = {9,5,10,7,2,3,1,6,8,4}; int i=0,j=0; int n = sizeof(a)/4; //外循环n-1轮 for(i=0;i<n-1;i++){ int pos = i;//始终指向最小的位置 for(j=i+1;j<n;j++){ if(a[j]<a[pos]){ pos = j

一句话的代码,从集合中找出第一个重复字符的方法javascript版。

有的时候需求是这样的: 找出集合中第一个重复的字符所在的位置,刚才看了园内某自许为算法的代码,感觉非常之啰嗦故写了以下代码! 本人对神马算法之类的完全不懂,但那些伪算法家们也别出来装蒜.一句话:不要欺负俺没文化好不好! 别的不说看代码: Array.prototype.searchFirstNotRepeat = function () { var curArr = this, val; while (-1 == (val = curArr.indexOf(curArr.shift())));

数论 - 整除问题 --- 整数集合中找出3的最大倍数

Mean: 题目描述:给一个包含非负整数的数组(长度为n),找出由这些数字组成的最大的3的倍数,没有的话则输出impossible. analyse: 首先想到的就是直接暴力,这是最蠢的方法,数据一大的话,必会TLE. 直接用蛮力的话,生成所有的组合,为 2^n个,对每个数字再进行比较判断,需要 O(n)的时间,因为n可能会比较大,需要每个位的比较.总的时间复杂度为O(n * 2^n). 那么到底要怎么做呢? 首先我们来了解几个数学知识: 1)一个数n对m取余的余数为a1,b为n的每一位数字的和

[面试题]在数组中找出3个数使得它们和为0

给定一个数组S,试找出3个数a, b, c,使得a+b+c=0.也即从集合中找出所有的和为0的3个数. 例如:集合S={-1,0, 1, 2, -1, 4},则满足条件的3个数有2对:(-1, 0, 1)和(-1, 2, -1).注意(-1,1,0)与(-1,0,1)算同一个解,所以不用重复考虑. 当然该例子集合的解也可以写成:(0, 1, -1)和(2, -1, -1). 参考了:http://blog.csdn.net/wangran51/article/details/8858398,他给

在由N个元素构成的集合S中,找出最小元素C,满足C=A-B,其中A,B是都集合S中的元素,没找到则返回-1

package bianchengti; /* * 在由N个元素构成的集合S中,找出最小元素C,满足C=A-B, * 其中A,B是都集合S中的元素,没找到则返回-1 */ public class findMinValue { //快速排序 public static void sort(int a[], int low, int hight) { if (low > hight) { return; } int i, j, key; i = low; j = hight; key = a[i]

海量日志数据__怎么在海量数据中找出重复次数最多的一个

问题一:         怎么在海量数据中找出重复次数最多的一个 算法思想:         方案1:先做hash,然后求模映射为小文件,求出每个小文件中重复次数最多的一个,并记录重复次数. 然后找出上一步求出的数据中重复次数最多的一个就是所求(如下). 问题二: 网站日志中记录了用户的IP,找出访问次数最多的IP. 算法思想:       IP地址最多有2^32=4G种取值可能,所以不能完全加载到内存中. 可以考虑分而治之的策略: map 按照IP地址的hash(IP)%1024值,将海量日志

一篇英文文档中找出频数最多的10个单词

"""一篇英文文档中找出频数最多的10个单词collections: Counter 提供计数器工具以支持方便和快速的计数 most_common(n) 返回n个最常见元素及其计数的列表,从最常见到最少. 如果省略nNone,则 most_common()返回计数器中的所有元素."""import refrom collections import Counter# print(dir(Counter))with open('english.tx

【c语言】第一个只出现一次的字符题目:在字符串中找出第一个只出现一次的字符

// 第一个只出现一次的字符题目:在字符串中找出第一个只出现一次的字符. // 如输入"abaccdeff",则输出'b'. #include <stdio.h> #include <string.h> char find_one(char *str) { int a[256]; int len = strlen(str); int i = 0; memset(a, 0, sizeof(a)); for (i = 0; i<len; i++) { a[st

Python List index()方法-用于从列表中找出某个值第一个匹配项的索引位置

描述 index() 函数用于从列表中找出某个值第一个匹配项的索引位置. 语法 index()方法语法: list.index(obj) 参数 obj -- 查找的对象. 返回值 该方法返回查找对象的索引位置,如果没有找到对象则抛出异常. 实例 以下实例展示了 index()函数的使用方法: #!/usr/bin/python aList = [123, 'xyz', 'zara', 'abc']; print "Index for xyz : ", aList.index( 'xyz