From b5dc741079e4845128397b1d061b38e172521d43 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 20 Aug 2022 00:38:00 +0800 Subject: [PATCH] fix code --- .../cn/hutool/core/collection/CollUtil.java | 141 ++---------------- .../core/collection/CollectionOperation.java | 130 +++++++++++++++- .../cn/hutool/core/collection/SetUtil.java | 11 ++ .../hutool/core/collection/CollUtilTest.java | 15 -- 4 files changed, 153 insertions(+), 144 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index 522d56e03..bb90147d4 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -364,28 +364,13 @@ public class CollUtil { * 结果:[a, b, c],此结果中只保留了一个c * * @param 集合元素类型 - * @param coll1 集合1 - * @param coll2 集合2 - * @param otherColls 其它集合 + * @param colls 集合列表 * @return 交集的集合,返回 {@link LinkedHashSet} * @since 5.3.9 */ @SafeVarargs - public static Set intersectionDistinct(final Collection coll1, final Collection coll2, final Collection... otherColls) { - // 任意容器为空, 则返回空集 - if (isEmpty(coll1) || isEmpty(coll2) || ArrayUtil.hasEmpty((Object[]) otherColls)) { - return new LinkedHashSet<>(); - } - final Set result = new LinkedHashSet<>(coll1); - result.retainAll(coll2); - - if (ArrayUtil.isNotEmpty(otherColls)) { - for (final Collection otherColl : otherColls) { - result.retainAll(otherColl); - } - } - - return result; + public static Set intersectionDistinct(final Collection... colls) { + return CollectionOperation.of(colls).intersectionDistinct(); } /** @@ -407,30 +392,7 @@ public class CollUtil { * @return 差集的集合,返回 {@link ArrayList} */ public static Collection disjunction(final Collection coll1, final Collection coll2) { - if (isEmpty(coll1) || isEmpty(coll2)) { - if (isEmpty(coll1) && isEmpty(coll2)) { - return ListUtil.zero(); - } else if (isEmpty(coll1)) { - return coll2; - } else if (isEmpty(coll2)) { - return coll1; - } - } - - final List result = new ArrayList<>(); - final Map map1 = countMap(coll1); - final Map map2 = countMap(coll2); - // 两个集合的全部元素 - final Set elements = SetUtil.of(map1.keySet()); - elements.addAll(map2.keySet()); - // 元素的个数为 该元素在两个集合中的个数的差 - for (final T t : elements) { - final int amount = Math.abs(map1.getOrDefault(t, 0) - map2.getOrDefault(t, 0)); - for (int i = 0; i < amount; i++) { - result.add(t); - } - } - return result; + return CollectionOperation.of(coll1, coll2).disjunction(); } /** @@ -469,23 +431,7 @@ public class CollUtil { * @since 5.3.5 */ public static List subtractToList(final Collection coll1, final Collection coll2) { - - if (isEmpty(coll1)) { - return ListUtil.empty(); - } - if (isEmpty(coll2)) { - return ListUtil.of(true, coll1); - } - - //将被交数用链表储存,防止因为频繁扩容影响性能 - final List result = new LinkedList<>(); - final Set set = new HashSet<>(coll2); - for (final T t : coll1) { - if (false == set.contains(t)) { - result.add(t); - } - } - return result; + return CollectionOperation.of(coll1, coll2).subtract(); } /** @@ -588,37 +534,8 @@ public class CollUtil { return false; } - // 针对Set的优化 - if (coll1 instanceof Set) { - //noinspection SuspiciousMethodCalls - return coll1.containsAll(coll2); - } - - final Iterator iterator = coll1.iterator(); - // 保存 集合1 已经遍历过的元素 - final Set elementsAlreadySeen = new HashSet<>(); - for (final Object curElement : coll2) { - // 集合2的当前元素 已经在集合1中 - if (elementsAlreadySeen.contains(curElement)) { - continue; - } - - // 集合2的当前元素 是否在集合1中 - boolean foundCurrentElement = false; - while (iterator.hasNext()) { - final Object next = iterator.next(); - elementsAlreadySeen.add(next); - if (Objects.equals(curElement, next)) { - foundCurrentElement = true; - break; - } - } - // 集合2的当前元素 不在集合1中, 显然不是子集 - if (!foundCurrentElement) { - return false; - } - } - return true; + //noinspection SuspiciousMethodCalls + return coll1.containsAll(coll2); } /** @@ -1771,11 +1688,14 @@ public class CollUtil { * @since 4.0.6 */ public static T get(final Collection collection, int index) { - if (isEmpty(collection)) { + if (null == collection) { return null; } final int size = collection.size(); + if (0 == size) { + return null; + } if (index < 0) { index += size; } @@ -2193,10 +2113,10 @@ public class CollUtil { if (isEmpty(mapCollection)) { return ListUtil.zero(); } - // 统计每个map的values的大小总和 + // 统计每个map的大小总和 int size = 0; for (final Map map : mapCollection) { - size += size(map.values()); + size += map.size(); } if (size == 0) { return ListUtil.zero(); @@ -2448,41 +2368,6 @@ public class CollUtil { return IterUtil.isEqualList(list1, list2); } - /** - * 判断两个集合是否包含相同的元素(包括个数) - * - * @param coll1 集合1 - * @param coll2 集合2 - * @return 两个集合是否相同 - * @since 6.0.0 - */ - public static boolean isEquals(final Collection coll1, final Collection coll2) { - if (coll1 == coll2) { - return true; - } - if (coll1 == null || coll2 == null || coll1.size() != coll2.size()) { - return false; - } - // 针对 Set 的优化 - if (coll1 instanceof Set || coll2 instanceof Set) { - //noinspection SuspiciousMethodCalls - return coll1 instanceof Set ? coll1.containsAll(coll2) : coll2.containsAll(coll1); - } - - // 给集合1的每个元素计数 - //noinspection unchecked - final Map countMap1 = countMap((Iterable) coll1); - - for (final Object e : coll2) { - // 该元素若存在, 则个数减去1, 若不存在则个数为-1 - final Integer amount = countMap1.merge(e, -1, Integer::sum); - if (amount < 0) { - return false; - } - } - return true; - } - /** * 一个对象不为空且不存在于该集合中时,加入到该集合中
*
diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollectionOperation.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollectionOperation.java
index 581823f1e..02fb31cbe 100755
--- a/hutool-core/src/main/java/cn/hutool/core/collection/CollectionOperation.java
+++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollectionOperation.java
@@ -11,7 +11,14 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * 集合运算
+ * 集合运算,包括:
+ * 
    + *
  • 求集合的并集
  • + *
  • 求集合的唯一并集
  • + *
  • 求集合的完全并集
  • + *
  • 求集合的交集
  • + *
  • 求集合的差集
  • + *
* * @param 集合元素类型 */ @@ -137,6 +144,82 @@ public class CollectionOperation { return result; } + /** + * 多个集合的唯一交集
+ * 针对一个集合中存在多个相同元素的情况,只保留一个
+ * 例如:集合1:[a, b, c, c, c],集合2:[a, b, c, c]
+ * 结果:[a, b, c],此结果中只保留了一个c + * + * @return 唯一交集的集合,返回 {@link LinkedHashSet} + */ + public Set intersectionDistinct() { + final Collection[] colls = this.colls; + // 任意容器为空, 则返回空集 + if (ArrayUtil.isEmpty(colls)) { + return SetUtil.zeroLinked(); + } + + final Set result = SetUtil.of(true, colls[0]); + for (int i = 1; i < colls.length; i++) { + if(CollUtil.isNotEmpty(colls[i])){ + result.retainAll(colls[i]); + } + } + + return result; + } + + /** + * 多个集合的差集
+ * 针对一个集合中存在多个相同元素的情况,计算每两个集合中此元素的个数,保留两个集合中此元素个数差的个数
+ * 例如: + * + *
+	 *     disjunction([a, b, c, c, c], [a, b, c, c]) -》 [c]
+	 *     disjunction([a, b], [])                    -》 [a, b]
+	 *     disjunction([a, b, c], [b, c, d])          -》 [a, d]
+	 * 
+ * 任意一个集合为空,返回另一个集合
+ * 两个集合无差集则返回空集合 + * + * @return 差集的集合,返回 {@link ArrayList} + */ + public Collection disjunction() { + final Collection[] colls = this.colls; + if (ArrayUtil.isEmpty(colls)) { + return ListUtil.zero(); + } + + Collection result = colls[0]; + for (int i = 1; i < colls.length; i++) { + result = _disjunction(result, colls[i]); + } + + return result; + } + + /** + * 计算集合的单差集,即只返回【集合1】中有,但是【集合2】、【集合3】...中没有的元素,例如: + * + *
+	 *     subtract([1,2,3,4],[2,3,4,5]) -》 [1]
+	 * 
+ * + * @return 单差集的List + */ + public List subtract() { + final Collection[] colls = this.colls; + if(ArrayUtil.isEmpty(colls)){ + return ListUtil.zero(); + } + final List result = ListUtil.of(colls[0]); + for (int i = 1; i < colls.length; i++) { + result.removeAll(colls[i]); + } + return result; + } + + // region private methods /** * 两个集合的并集
* 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留最多的个数
@@ -206,4 +289,49 @@ public class CollectionOperation { } return list; } + + /** + * 两个集合的差集
+ * 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留两个集合中此元素个数差的个数
+ * 例如: + * + *
+	 *     disjunction([a, b, c, c, c], [a, b, c, c]) -》 [c]
+	 *     disjunction([a, b], [])                    -》 [a, b]
+	 *     disjunction([a, b, c], [b, c, d])          -》 [a, d]
+	 * 
+ * 任意一个集合为空,返回另一个集合
+ * 两个集合无差集则返回空集合 + * + * @param 集合元素类型 + * @param coll1 集合1 + * @param coll2 集合2 + * @return 差集的集合,返回 {@link ArrayList} + */ + private static Collection _disjunction(final Collection coll1, final Collection coll2) { + if(CollUtil.isEmpty(coll1)){ + if(CollUtil.isEmpty(coll2)){ + return ListUtil.zero(); + } + return coll2; + } else if(CollUtil.isEmpty(coll2)){ + return coll1; + } + + final List result = new ArrayList<>(coll1.size() + coll2.size()); + final Map map1 = CollUtil.countMap(coll1); + final Map map2 = CollUtil.countMap(coll2); + // 两个集合的全部元素 + final Set elements = SetUtil.of(map1.keySet()); + elements.addAll(map2.keySet()); + // 元素的个数为 该元素在两个集合中的个数的差 + for (final T t : elements) { + final int amount = Math.abs(map1.getOrDefault(t, 0) - map2.getOrDefault(t, 0)); + for (int i = 0; i < amount; i++) { + result.add(t); + } + } + return result; + } + // endregion } diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/SetUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/SetUtil.java index 8a99dc73f..e6359128f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/SetUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/SetUtil.java @@ -186,6 +186,17 @@ public class SetUtil { return new HashSet<>(0, 1); } + /** + * 获取一个初始大小为0的LinkedHashSet,这个空Set可变 + * + * @param 元素类型 + * @return 空的List + * @since 6.0.0 + */ + public static Set zeroLinked() { + return new LinkedHashSet<>(0, 1); + } + /** * 转为只读Set * diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java index 1ed0393c7..e3fcf9643 100755 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java @@ -1121,19 +1121,4 @@ public class CollUtilTest { Assert.assertFalse(CollUtil.isEqualList(list, ListUtil.of(1, 2, 3))); Assert.assertFalse(CollUtil.isEqualList(list, ListUtil.of(4, 3, 2, 1))); } - - @Test - public void isEqualsTest() { - final List list = ListUtil.of(1, 2, 3, 4); - Assert.assertTrue(CollUtil.isEquals(null, null)); - Assert.assertTrue(CollUtil.isEquals(ListUtil.of(), ListUtil.of())); - Assert.assertTrue(CollUtil.isEquals(list, list)); - Assert.assertTrue(CollUtil.isEquals(list, ListUtil.of(1, 2, 3, 4))); - Assert.assertTrue(CollUtil.isEquals(list, ListUtil.of(4, 3, 2, 1))); - Assert.assertTrue(CollUtil.isEquals(list, SetUtil.of(4, 3, 2, 1))); - - Assert.assertFalse(CollUtil.isEquals(null, ListUtil.of())); - Assert.assertFalse(CollUtil.isEquals(list, ListUtil.of(1, 2, 3, 3))); - Assert.assertFalse(CollUtil.isEquals(list, ListUtil.of(1, 2, 3))); - } }