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 extends V> 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 extends V> 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};