Java中取多个集合的交集
集合 Collection 接口中定义了 retainAll()方法
retainAll()
Retains only the elements in this set that are contained in the specified collection (optional operation). In other words, removes from this set all of its elements that are not contained in the specified collection. If the specified collection is also a set, this operation effectively modifies this set so that its value is the intersection of the two sets.
简单来说,该方法目的是取当前集合及参数指定集合的一个交集,并修改当前集合,仅保留交集元素。
下图是集合类框架的一个架构图:
通过这个架构图,可以在大脑中对集合这块的类有个清晰的定位。
抽象类 AbstractCollection 中对 retainAll() 方法进行了实现。 使用Set集合的 retainAll() 方法,其实就是调用了AbstractCollection中的 retainAll()方法。
其底层其实使用的 contains() 方法进行判断元素是否存在集合中。对于当前集合中的元素进行遍历,判断每个元素是否存在于参数集合中,若不存在则从当前集合中移除该元素,最终保留的就是两个集合共有的元素。
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
对于 ArrayList 类,对 retainAll() 方法进行了重写。其中的核心思路是一样的。
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, 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 {
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
对于多个集合取交集(不确定集合的个数)
思路:创建一个新的 List 集合,将目标集合都放入新创建的 List 集合中,若有条件过滤,可使用stream流进行条件筛选(比如去掉空集合),最终得到结果 List 集合。 然后遍历该集合,使用集合中的第一个集合一次和后续的每个集合取交集,即可得到所有集合的交集。
Set set1 = new HashSet();
Set set2 = new HashSet();
Set set3 = new HashSet();
set1.add("1");
set2.add("1");
set2.add("2");
set3.add("1");
List<Set> setList = new ArrayList<>();
setList.add(set1);
setList.add(set2);
setList.add(set3);
Set resultSet = setList.get(0);
resultSetList.forEach(item -> {
resultSet.retainAll(item);
});
再复杂的东西都是由简单的东西组成的,只因量变达到质变。
|