java 两个list的交集 并集 差集 去重复并集
文章摘要
在Java中,List集合可通过特定方法求交集、差集和并集:差集用removeAll,交集用retainAll;并集不去重用addAll,去重则先removeAll再addAll。这些操作会修改原List,而另一个List保持不变。
前提需要明白List是引用类型,引用类型采用引用传递。   我们经常会遇到一些需求求集合的交集、差集、并集。例如下面两个集合: ```java List list1 = new ArrayList(); list1.add("A"); list1.add("B"); List list2 = new ArrayList(); list2.add("B"); list2.add("C"); ``` ### 0.求差集   例如,求List1中有的但是List2中没有的元素: ```java public static void test3(List list1, List list2) { list1.removeAll(list2); System.out.println(list1); } ``` 结果: [A] 查看ArrayList的removeAll的源码 ```java public boolean removeAll(Collection c) { Objects.requireNonNull(c); return batchRemove(c, false); } ``` 再查看batchRemove的源码:(如果传的第二个参数是false,保留差集;如果传的是true,保留的是交集) ```java private boolean batchRemove(Collection c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; } ```   是重新定义elementData数组的元素,下面代码的作用是将本集合中不包含另一个集合的元素重新加入元素,以此实现删除的功能(注意上面调用的方法传的参数是false,也就是不包含的元素得以保留,实现差集的功能) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; ### **1.求并集(不去重)---将一个集合全部加入另一个集合** ```java public static void test(List list1, List list2) { list1.addAll(list2); System.out.println(list1); } ``` 结果: [A, B, B, C] 查看ArayList的addAll()源码是数组复制: ```java public boolean addAll(Collection c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } ``` 再查看System的arraycopy发现是一个native方法(本地方法):---其实system类的好多方法都是native方法 ```java public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); ``` ### **2.求并集(去重)**   **例如:求List1和List2的并集,并实现去重。**     **思路是:先将list中与list2重复的去掉,之后将list2的元素全部添加进去。** ```java public static void test1(List list1, List list2) { list1.removeAll(list2); list1.addAll(list2); System.out.println(list1); } ``` 结果: [A, B, C] ### 3.求交集   例如:求List1和List2中都有的元素。 ```java public static void test2(List list1, List list2) { list1.retainAll(list2); System.out.println(list1); } ``` 结果: [B] 在上面2的实验过程中,我们知道batchRemove(Collection,true)也是求交集,所以猜想 retainAll 内部应该是调用 batchRemove(Collection,true),查看ArrayList的源码如下: ```java public boolean retainAll(Collection c) { Objects.requireNonNull(c); return batchRemove(c, true); } ``` # [list的交集,差集,并集](https://www.cnblogs.com/changfanchangle/p/8966860.html) [java 判断两个list是否相等](https://www.cnblogs.com/dtest/p/5084776.html) 工作中用到了list的取差集,发现还是挺好用的。 所以记录下。 | 需求 | list的方法 | 说明 | 备注 | | ---- | ------------------------------------------ | -------------------------------------------- | --------- | | 交集 | listA.retainAll(listB) | listA内容变为listA和listB都存在的对象 | listB不变 | | 差集 | listA.removeAll(listB) | listA中存在的listB的内容去重 | listB不变 | | 并集 | listA.removeAll(listB) listA.addAll(listB) | 为了去重,listA先取差集,然后追加全部的listB | listB不变 | 测试代码: ```java // 交集 List listA_01 = new ArrayList(){{ add("A"); add("B"); }}; List listB_01 = new ArrayList(){{ add("B"); add("C"); }}; listA_01.retainAll(listB_01); System.out.println(listA_01); // 结果:[B] System.out.println(listB_01); // 结果:[B, C] // 差集 List listA_02 = new ArrayList(){{ add("A"); add("B"); }}; List listB_02 = new ArrayList(){{ add("B"); add("C"); }}; listA_02.removeAll(listB_02); System.out.println(listA_02); // 结果:[A] System.out.println(listB_02); // 结果:[B, C] // 并集 List listA_03 = new ArrayList(){{ add("A"); add("B"); }}; List listB_03 = new ArrayList(){{ add("B"); add("C"); }}; listA_03.removeAll(listB_03); listA_03.addAll(listB_03); System.out.println(listA_03); // 结果:[A, B, C] System.out.println(listB_03); // 结果:[B, C] ``` # ```java /** * 队列比较 * @param * @param a * @param b * @return */ public static > boolean compare(List a, List b) { if(a.size() != b.size()) return false; Collections.sort(a); Collections.sort(b); for(int i=0;i a = Arrays.asList(1,2,3,4); List b = Arrays.asList(4,3,2,1); System.out.println(compare(a, b)); } //执行结果 true ```
作者头像
admin
分享技术与生活
打赏作者

评论

暂无评论,快来抢沙发吧~