list交并补差集合
工具类依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2</version>
</dependency>
参考代码
类图
核心api
交集
public static <O> Collection<O> intersection(final Iterable<? extends O> a, final Iterable<? extends O> b) {
final SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<>(a, b);
for (final O obj : helper) {
helper.setCardinality(obj, helper.min(obj));
}
return helper.list();
}
并集
public static <O> Collection<O> union(final Iterable<? extends O> a, final Iterable<? extends O> b) {
final SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<>(a, b);
for (final O obj : helper) {
helper.setCardinality(obj, helper.max(obj));
}
return helper.list();
}
差集
public static <O> Collection<O> subtract(final Iterable<? extends O> a, final Iterable<? extends O> b) {
final Predicate<O> p = TruePredicate.truePredicate();
return subtract(a, b, p);
}
补集
public static <O> Collection<O> disjunction(final Iterable<? extends O> a, final Iterable<? extends O> b) {
final SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<>(a, b);
for (final O obj : helper) {
helper.setCardinality(obj, helper.max(obj) - helper.min(obj));
}
return helper.list();
}
案例说明
// 交并补差
List<Integer> list1 = Lists.newArrayList(1,2,3);
List<Integer> list2 = Lists.newArrayList(3,4,5);
List<Integer> intersection = (List<Integer>) CollectionUtils.intersection(list1, list2);
log.info("list1与list2交集:[{}]",intersection);
List<Integer> unionResult = (List<Integer>) CollectionUtils.union(list1, list2);
log.info("list1与list2并集:[{}]",unionResult);
List<Integer> subtractList = (List<Integer>) CollectionUtils.subtract(list1, list2);
log.info("list1与list2差集:[{}]",subtractList);
List<Integer> subtractListSecond = (List<Integer>) CollectionUtils.subtract(list2, list1);
log.info("list2与list1差集:[{}]",subtractListSecond);
List<Integer> disjunctionList = (List<Integer>) CollectionUtils.disjunction(list1, list2);
log.info("list1与list2补集:[{}]",disjunctionList);
00:05:52.126 [main] INFO com.geekmice.sbeasypoi.service.impl.ds - list1与list2交集:[[3]]
00:05:52.136 [main] INFO com.geekmice.sbeasypoi.service.impl.ds - list1与list2并集:[[1, 2, 3, 4, 5]]
00:05:52.147 [main] INFO com.geekmice.sbeasypoi.service.impl.ds - list1与list2差集:[[1, 2]]
00:05:52.147 [main] INFO com.geekmice.sbeasypoi.service.impl.ds - list2与list1差集:[[4, 5]]
00:05:52.149 [main] INFO com.geekmice.sbeasypoi.service.impl.ds - list1与list2补集:[[1, 2, 4, 5]]
源码分析
交集核心逻辑:
存储所有元素,set操作,已经去重;
用两个map存储两个集合,map中key数值,value表示出现次数
从第一个元素开始计算,如果在map1中,不在map2中,不记录
依次操作,如果在map2,不在map1中,不记录;
如果都存在的话,记录新的list当中,最后返回list.
public final int min(final Object obj) {
return Math.min(freqA(obj), freqB(obj));
}
并集核心逻辑
存储所有元素,set操作,已经去重;
用两个map存储两个集合,map中key数值,value表示出现次数
从第一个元素开始计算,只要存在两个map任意一个当中,记录新的容器。
public final int max(final Object obj) {
return Math.max(freqA(obj), freqB(obj));
}
补集核心逻辑
简单理解就是并集-交集
只要交集和并集逻辑捋顺,这个简单多了。
public static <O> Collection<O> disjunction(final Iterable<? extends O> a, final Iterable<? extends O> b) {
final SetOperationCardinalityHelper<O> helper = new SetOperationCardinalityHelper<>(a, b);
for (final O obj : helper) {
helper.setCardinality(obj, helper.max(obj) - helper.min(obj));
}
return helper.list();
}
差集核心逻辑
a-b:就是a集合减去a与b交集就是a差集
先记录一下b集合放在map里面,再处理list1,
遍历处理,如果存在map里面不添加新的容器里面,
不存在的话,添加新容器。
public static <O> Collection<O> subtract(final Iterable<? extends O> a,
final Iterable<? extends O> b,
final Predicate<O> p) {
final ArrayList<O> list = new ArrayList<>();
final HashBag<O> bag = new HashBag<>();
for (final O element : b) {
if (p.evaluate(element)) {
bag.add(element);
}
}
for (final O element : a) {
if (!bag.remove(element, 1)) {
list.add(element);
}
}
return list;
}