From 7e36d0f0760ea2153a2fb02e4b768ba47743f9e6 Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 17 Apr 2022 08:53:43 +0800 Subject: [PATCH] add method --- CHANGELOG.md | 4 ++- .../cn/hutool/core/collection/CollUtil.java | 25 ++++++++++++++++ .../hutool/core/collection/UniqueKeySet.java | 25 ++++++++++++++++ .../cn/hutool/core/text/CharSequenceUtil.java | 6 ++-- .../java/cn/hutool/core/util/ArrayUtil.java | 29 ++++++++++++++++++ .../hutool/core/collection/CollUtilTest.java | 30 +++++++++++++++++++ .../cn/hutool/core/util/ArrayUtilTest.java | 13 ++++++++ 7 files changed, 128 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7768b1bd0..ec5c7c1d9 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.8.0.M4 (2022-04-16) +# 5.8.0.M4 (2022-04-17) ### ❌不兼容特性 * 【json 】 【可能兼容问题】JSONArray删除部分构造 @@ -12,8 +12,10 @@ * 【core 】 BeanUtil增加toBean重载(pr#598@Gitee) * 【json 】 新增JSONParser * 【json 】 JSON新增在解析时的过滤方法(issue#I52O85@Gitee) +* 【core 】 添加ArrayUtil.distinct、CollUtil.distinct重载(issue#2256@Github) ### 🐞Bug修复 +* 【core 】 修复StrUtil.firstNonX非static问题(issue#2257@Github) ------------------------------------------------------------------------------------------------------------- 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 b5a024124..cae324ed4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -1051,6 +1051,31 @@ public class CollUtil { } } + /** + * 根据函数生成的KEY去重集合,如根据Bean的某个或者某些字段完成去重。
+ * 去重可选是保留最先加入的值还是后加入的值 + * + * @param 集合元素类型 + * @param 唯一键类型 + * @param collection 集合 + * @param override 是否覆盖模式,如果为{@code true},加入的新值会覆盖相同key的旧值,否则会忽略新加值 + * @return {@link ArrayList} + * @since 5.8.0 + */ + public static List distinct(Collection collection, Function uniqueGenerator, boolean override) { + if (isEmpty(collection)) { + return new ArrayList<>(); + } + + final UniqueKeySet set = new UniqueKeySet<>(true, uniqueGenerator); + if (override) { + set.addAll(collection); + } else { + set.addAllIfAbsent(collection); + } + return new ArrayList<>(set); + } + /** * 截取列表的部分 * diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/UniqueKeySet.java b/hutool-core/src/main/java/cn/hutool/core/collection/UniqueKeySet.java index f4fbcb15c..8f2aa4f66 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/UniqueKeySet.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/UniqueKeySet.java @@ -42,6 +42,17 @@ public class UniqueKeySet extends AbstractSet implements Serializable { this(false, uniqueGenerator); } + /** + * 构造 + * + * @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键 + * @param c 初始化加入的集合 + * @since 5.8.0 + */ + public UniqueKeySet(Function uniqueGenerator, Collection c) { + this(false, uniqueGenerator, c); + } + /** * 构造 * @@ -52,6 +63,19 @@ public class UniqueKeySet extends AbstractSet implements Serializable { this(MapBuilder.create(isLinked), uniqueGenerator); } + /** + * 构造 + * + * @param isLinked 是否保持加入顺序 + * @param uniqueGenerator 唯一键生成规则函数,用于生成对象对应的唯一键 + * @param c 初始化加入的集合 + * @since 5.8.0 + */ + public UniqueKeySet(boolean isLinked, Function uniqueGenerator, Collection c) { + this(isLinked, uniqueGenerator); + addAll(c); + } + /** * 构造 * @@ -73,6 +97,7 @@ public class UniqueKeySet extends AbstractSet implements Serializable { this.map = builder.build(); this.uniqueGenerator = uniqueGenerator; } + //endregion @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java index 529ed00dc..6c7c45382 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java @@ -3879,7 +3879,7 @@ public class CharSequenceUtil { * @since 5.4.1 */ @SuppressWarnings("unchecked") - public T firstNonNull(T... strs) { + public static T firstNonNull(T... strs) { return ArrayUtil.firstNonNull(strs); } @@ -3893,7 +3893,7 @@ public class CharSequenceUtil { * @since 5.4.1 */ @SuppressWarnings("unchecked") - public T firstNonEmpty(T... strs) { + public static T firstNonEmpty(T... strs) { return ArrayUtil.firstMatch(StrUtil::isNotEmpty, strs); } @@ -3907,7 +3907,7 @@ public class CharSequenceUtil { * @since 5.4.1 */ @SuppressWarnings("unchecked") - public T firstNonBlank(T... strs) { + public static T firstNonBlank(T... strs) { return ArrayUtil.firstMatch(StrUtil::isNotBlank, strs); } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index 4ba720987..9e535b668 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -2,6 +2,7 @@ package cn.hutool.core.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.UniqueKeySet; import cn.hutool.core.comparator.CompareUtil; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.lang.Assert; @@ -1633,6 +1634,34 @@ public class ArrayUtil extends PrimitiveArrayUtil { return toArray(set, (Class) getComponentType(array)); } + /** + * 去重数组中的元素,去重后生成新的数组,原数组不变
+ * 此方法通过{@link LinkedHashSet} 去重 + * + * @param 数组元素类型 + * @param 唯一键类型 + * @param array 数组 + * @param override 是否覆盖模式,如果为{@code true},加入的新值会覆盖相同key的旧值,否则会忽略新加值 + * @return 去重后的数组 + * @since 5.8.0 + */ + @SuppressWarnings("unchecked") + public static T[] distinct(T[] array, Function uniqueGenerator, boolean override) { + if (isEmpty(array)) { + return array; + } + + final UniqueKeySet set = new UniqueKeySet<>(true, uniqueGenerator); + if(override){ + Collections.addAll(set, array); + } else{ + for (T t : array) { + set.addIfAbsent(t); + } + } + return toArray(set, (Class) getComponentType(array)); + } + /** * 按照指定规则,将一种类型的数组转换为另一种类型 * 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 ad0582e18..512b13e2d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java @@ -878,6 +878,36 @@ public class CollUtilTest { Assert.assertEquals(people.get(1).getGender(), "小孩"); } + @Test + public void distinctTest(){ + final ArrayList distinct = CollUtil.distinct(ListUtil.of(5, 3, 10, 9, 0, 5, 10, 9)); + Assert.assertEquals(ListUtil.of(5, 3, 10, 9, 0), distinct); + } + + @Test + public void distinctByFunctionTest(){ + List people = Arrays.asList( + new Person("aa", 12, "man", 1), + new Person("bb", 13, "woman", 2), + new Person("cc", 14, "man", 3), + new Person("dd", 15, "woman", 4), + new Person("ee", 16, "woman", 5), + new Person("ff", 17, "man", 6) + ); + + // 覆盖模式下ff覆盖了aa,ee覆盖了bb + List distinct = CollUtil.distinct(people, Person::getGender, true); + Assert.assertEquals(2, distinct.size()); + Assert.assertEquals("ff", distinct.get(0).getName()); + Assert.assertEquals("ee", distinct.get(1).getName()); + + // 非覆盖模式下,保留了最早加入的aa和bb + distinct = CollUtil.distinct(people, Person::getGender, false); + Assert.assertEquals(2, distinct.size()); + Assert.assertEquals("aa", distinct.get(0).getName()); + Assert.assertEquals("bb", distinct.get(1).getName()); + } + @Data @AllArgsConstructor static class Person { diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java index 92f3603a8..de3f0d911 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java @@ -285,6 +285,19 @@ public class ArrayUtilTest { Assert.assertArrayEquals(new String[]{"aa", "bb", "cc", "dd"}, distinct); } + @Test + public void distinctByFunctionTest() { + String[] array = {"aa", "Aa", "BB", "bb"}; + + // 覆盖模式下,保留最后加入的两个元素 + String[] distinct = ArrayUtil.distinct(array, String::toLowerCase, true); + Assert.assertArrayEquals(new String[]{"Aa", "bb"}, distinct); + + // 忽略模式下,保留最早加入的两个元素 + distinct = ArrayUtil.distinct(array, String::toLowerCase, false); + Assert.assertArrayEquals(new String[]{"aa", "BB"}, distinct); + } + @Test public void toStingTest() { int[] a = {1, 3, 56, 6, 7};