diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f4381165..c9ff043ed 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.26(2024-01-25) +# 5.8.26(2024-01-26) ### 🐣新特性 * 【db 】 RedisDS增加user支持(issue#I8XEQ4@Gitee) @@ -13,6 +13,7 @@ * 【core 】 修复BeanToMapCopier获取类型数组越界问题(issue#3468@Github) * 【extra 】 修复SshjSftpSession关闭导致的问题(issue#3472@Github) * 【http 】 修复HtmlUtil.removeHtmlAttr处理空格问题(issue#I8YV0K@Gitee) +* 【core 】 修复CollUtil.containsAll在coll2长度大于coll1时逻辑歧义问题(issue#I8Z2Q4@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.8.25(2024-01-11) 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 a597a063c..b2fe32234 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 @@ -7,10 +7,7 @@ import cn.hutool.core.comparator.PropertyComparator; import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.ConverterRegistry; import cn.hutool.core.exceptions.UtilException; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Editor; -import cn.hutool.core.lang.Filter; -import cn.hutool.core.lang.Matcher; +import cn.hutool.core.lang.*; import cn.hutool.core.lang.func.Func1; import cn.hutool.core.lang.hash.Hash32; import cn.hutool.core.map.MapUtil; @@ -496,13 +493,16 @@ public class CollUtil { } /** - * 集合1中是否包含集合2中所有的元素,即集合2是否为集合1的子集 + * 集合1中是否包含集合2中所有的元素。
+ * 当集合1和集合2都为空时,返回{@code true} + * 当集合2为空时,返回{@code true} * * @param coll1 集合1 * @param coll2 集合2 * @return 集合1中是否包含集合2中所有的元素 * @since 4.5.12 */ + @SuppressWarnings("SuspiciousMethodCalls") public static boolean containsAll(Collection coll1, Collection coll2) { if (isEmpty(coll1)) { return isEmpty(coll2); @@ -512,12 +512,31 @@ public class CollUtil { return true; } - if (coll1.size() < coll2.size()) { - return false; + // Set直接判定 + if(coll1 instanceof Set){ + return coll1.containsAll(coll2); } - for (Object object : coll2) { - if (false == coll1.contains(object)) { + // 参考Apache commons collection4 + // 将时间复杂度降低到O(n + m) + final Iterator it = coll1.iterator(); + final Set elementsAlreadySeen = new HashSet<>(coll1.size(), 1); + for (final Object nextElement : coll2) { + if (elementsAlreadySeen.contains(nextElement)) { + continue; + } + + boolean foundCurrentElement = false; + while (it.hasNext()) { + final Object p = it.next(); + elementsAlreadySeen.add(p); + if (Objects.equals(nextElement, p)) { + foundCurrentElement = true; + break; + } + } + + if (false == foundCurrentElement) { return false; } } 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 585c1cd6d..99bdf2068 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 @@ -1084,4 +1084,20 @@ public class CollUtilTest { Assert.assertNull(CollUtil.max(null)); } + @Test + public void issueI8Z2Q4Test() { + ArrayList coll1 = new ArrayList<>(); + coll1.add("1"); + coll1.add("2"); + coll1.add("3"); + coll1.add("4"); + ArrayList coll2 = new ArrayList<>(); + coll2.add("1"); + coll2.add("1"); + coll2.add("1"); + coll2.add("1"); + coll2.add("1"); + + Assert.assertTrue(CollUtil.containsAll(coll1, coll2)); + } }