快速从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的方式