diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/comparator/ArrayIndexedComparator.java b/hutool-core/src/main/java/org/dromara/hutool/core/comparator/ArrayIndexedComparator.java
new file mode 100644
index 000000000..c157cb2f2
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/comparator/ArrayIndexedComparator.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * https://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.core.comparator;
+
+import org.dromara.hutool.core.lang.Assert;
+import org.dromara.hutool.core.array.ArrayUtil;
+
+import java.util.Comparator;
+
+/**
+ * 按照数组的顺序正序排列,数组的元素位置决定了对象的排序先后
+ * 默认的,如果参与排序的元素并不在数组中,则排序在前(可以通过atEndIfMiss设置)
+ *
+ * @param 被排序元素类型
+ * @author looly
+ * @since 4.1.5
+ */
+public class ArrayIndexedComparator implements Comparator {
+
+ private final boolean atEndIfMiss;
+ private final T[] array;
+
+ /**
+ * 构造
+ *
+ * @param objs 参与排序的数组,数组的元素位置决定了对象的排序先后
+ */
+ @SuppressWarnings("unchecked")
+ public ArrayIndexedComparator(final T... objs) {
+ this(false, objs);
+ }
+
+ /**
+ * 构造
+ *
+ * @param atEndIfMiss 如果不在列表中是否排在后边
+ * @param objs 参与排序的数组,数组的元素位置决定了对象的排序先后
+ */
+ @SuppressWarnings("unchecked")
+ public ArrayIndexedComparator(final boolean atEndIfMiss, final T... objs) {
+ Assert.notNull(objs, "'objs' array must not be null");
+ this.atEndIfMiss = atEndIfMiss;
+ this.array = objs;
+ }
+
+ @Override
+ public int compare(final T o1, final T o2) {
+ final int index1 = getOrder(o1);
+ final int index2 = getOrder(o2);
+
+ // 任意一个元素不在列表中
+ if(index1 == index2){
+ if(index1 < 0 || index1 == this.array.length){
+ // 任意一个元素不在列表中, 返回原顺序
+ return 1;
+ }
+ }
+
+ return Integer.compare(index1, index2);
+ }
+
+ /**
+ * 查找对象类型所在列表的位置
+ *
+ * @param object 对象
+ * @return 位置,未找到位置根据{@link #atEndIfMiss}取不同值,false返回-1,否则返回列表长度
+ */
+ private int getOrder(final T object) {
+ int order = ArrayUtil.indexOf(array, object);
+ if (order < 0) {
+ order = this.atEndIfMiss ? this.array.length : -1;
+ }
+ return order;
+ }
+}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/comparator/CompareUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/comparator/CompareUtil.java
index f23dec093..2dbf2e38a 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/comparator/CompareUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/comparator/CompareUtil.java
@@ -335,7 +335,7 @@ public class CompareUtil {
@SuppressWarnings("unchecked")
public static Comparator comparingIndexed(final Function super T, ? extends U> keyExtractor, final boolean atEndIfMiss, final U... objs) {
Objects.requireNonNull(keyExtractor);
- final IndexedComparator indexedComparator = new IndexedComparator<>(atEndIfMiss, objs);
+ final ArrayIndexedComparator indexedComparator = new ArrayIndexedComparator<>(atEndIfMiss, objs);
return (o1, o2) -> indexedComparator.compare(keyExtractor.apply(o1), keyExtractor.apply(o2));
}
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/comparator/IndexedComparator.java b/hutool-core/src/main/java/org/dromara/hutool/core/comparator/IndexedComparator.java
index bd732d9ff..fb2111b50 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/comparator/IndexedComparator.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/comparator/IndexedComparator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Copyright (c) 2024. looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
@@ -13,9 +13,10 @@
package org.dromara.hutool.core.comparator;
import org.dromara.hutool.core.lang.Assert;
-import org.dromara.hutool.core.array.ArrayUtil;
import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
/**
* 按照数组的顺序正序排列,数组的元素位置决定了对象的排序先后
@@ -28,7 +29,10 @@ import java.util.Comparator;
public class IndexedComparator implements Comparator {
private final boolean atEndIfMiss;
- private final T[] array;
+ /**
+ * map存储对象类型所在列表的位置,k为对象,v为位置
+ */
+ private final Map super T, Integer> map;
/**
* 构造
@@ -40,6 +44,18 @@ public class IndexedComparator implements Comparator {
this(false, objs);
}
+
+ /**
+ * 构造
+ *
+ * @param atEndIfMiss 如果不在列表中是否排在后边
+ * @param map 参与排序的map,map中的value值大小决定了对象的排序先后
+ */
+ public IndexedComparator(final boolean atEndIfMiss, final Map super T, Integer> map) {
+ this.atEndIfMiss = atEndIfMiss;
+ this.map = map;
+ }
+
/**
* 构造
*
@@ -50,7 +66,10 @@ public class IndexedComparator implements Comparator {
public IndexedComparator(final boolean atEndIfMiss, final T... objs) {
Assert.notNull(objs, "'objs' array must not be null");
this.atEndIfMiss = atEndIfMiss;
- this.array = objs;
+ map = new HashMap<>(objs.length, 1);
+ for (int i = 0; i < objs.length; i++) {
+ map.put(objs[i], i);
+ }
}
@Override
@@ -58,27 +77,29 @@ public class IndexedComparator implements Comparator {
final int index1 = getOrder(o1);
final int index2 = getOrder(o2);
- // 任意一个元素不在列表中
- if(index1 == index2){
- if(index1 < 0 || index1 == this.array.length){
- // 任意一个元素不在列表中, 返回原顺序
+ if (index1 == index2) {
+ if (index1 < 0 || index1 == this.map.size()) {
+ // 任意一个元素不在map中, 返回原顺序
return 1;
}
+
+ // 位置一样,认为是同一个元素
+ return 0;
}
return Integer.compare(index1, index2);
}
/**
- * 查找对象类型所在列表的位置
+ * 查找对象类型所对应的顺序值,即在原列表中的顺序
*
* @param object 对象
- * @return 位置,未找到位置根据{@link #atEndIfMiss}取不同值,false返回-1,否则返回列表长度
+ * @return 位置,未找到位置根据{@link #atEndIfMiss}取不同值,false返回-1,否则返回map长度
*/
private int getOrder(final T object) {
- int order = ArrayUtil.indexOf(array, object);
- if (order < 0) {
- order = this.atEndIfMiss ? this.array.length : -1;
+ Integer order = map.get(object);
+ if (order == null) {
+ order = this.atEndIfMiss ? this.map.size() : -1;
}
return order;
}
diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/comparator/IndexedComparatorTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/comparator/IndexedComparatorTest.java
new file mode 100644
index 000000000..b1ecdbc63
--- /dev/null
+++ b/hutool-core/src/test/java/org/dromara/hutool/core/comparator/IndexedComparatorTest.java
@@ -0,0 +1,78 @@
+package org.dromara.hutool.core.comparator;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.dromara.hutool.core.collection.CollUtil;
+import org.dromara.hutool.core.date.StopWatch;
+import org.dromara.hutool.core.lang.Console;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * https://gitee.com/dromara/hutool/pulls/1240
+ */
+public class IndexedComparatorTest {
+ @Test
+ public void sortTest() {
+ final Object[] arr = {"a", "b", new User("9", null), "1", 3, null, "2"};
+ final Collection