网站首页 > 技术文章 正文
前提需要明白List是引用类型,引用类型采用引用传递。
我们经常会遇到一些需求求集合的交集、差集、并集。例如下面两个集合:
List<String> list1 = new ArrayList<String>(); list1.add("A"); list1.add("B"); List<String> list2 = new ArrayList<String>(); list2.add("B"); list2.add("C");
0.求差集
例如,求List1中有的但是List2中没有的元素:
public static void test3(List list1, List list2) { list1.removeAll(list2); System.out.println(list1); }
结果:
[A]
查看ArrayList的removeAll的源码
public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); }
再查看batchRemove的源码:(如果传的第二个参数是false,保留差集;如果传的是true,保留的是交集)
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.求并集(不去重)---将一个集合全部加入另一个集合
public static void test(List list1, List list2) { list1.addAll(list2); System.out.println(list1); }
结果:
[A, B, B, C]
查看ArayList的addAll()源码是数组复制:
public boolean addAll(Collection<? extends E> 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方法
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
2.求并集(去重)
例如:求List1和List2的并集,并实现去重。
思路是:先将list中与list2重复的去掉,之后将list2的元素全部添加进去。
public static void test1(List list1, List list2) { list1.removeAll(list2); list1.addAll(list2); System.out.println(list1); }
结果:
[A, B, C]
3.求交集
例如:求List1和List2中都有的元素。
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的源码如下:
public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); }
- 上一篇: PHP一维数组交、差、并、合集操作
- 下一篇: PHP检查数组中缺少的数字(php数组是否存在key)
猜你喜欢
- 2024-10-16 python数据类型(python数据类型bool)
- 2024-10-16 JavaScript Set、Map、WeakSet 和 WeakMap 的区别?
- 2024-10-16 69-1-10000遗漏了哪些序号#差集#Filter...
- 2024-10-16 进入Python的世界12-常用的程序例子整理二
- 2024-10-16 Java路径-35-Java的HashSet(java路径怎么找)
- 2024-10-16 Redis五种数据类型详解(redis7种数据类型)
- 2024-10-16 那些你不得不知的Redis基础类型常用操作、命令
- 2024-10-16 美团外卖iOS App冷启动治理(美团早启动)
- 2024-10-16 (Python)通过口诀记忆数组、集合、字典、元组
- 2024-10-16 【C++泛型编程】(二)标准模板库 STL
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)