diff --git a/hutool-core/src/main/java/cn/hutool/core/comparator/IndexedComparator.java b/hutool-core/src/main/java/cn/hutool/core/comparator/IndexedComparator.java index d54cd3c2f..71026b22e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/comparator/IndexedComparator.java +++ b/hutool-core/src/main/java/cn/hutool/core/comparator/IndexedComparator.java @@ -1,9 +1,10 @@ package cn.hutool.core.comparator; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ArrayUtil; import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; /** * 按照数组的顺序正序排列,数组的元素位置决定了对象的排序先后
@@ -16,7 +17,10 @@ import java.util.Comparator; public class IndexedComparator implements Comparator { private final boolean atEndIfMiss; - private final T[] array; + /** + * map存储对象类型所在列表的位置,k为对象,v为位置 + */ + private final Map map; /** * 构造 @@ -28,6 +32,19 @@ public class IndexedComparator implements Comparator { this(false, objs); } + + /** + * 构造 + * + * @param atEndIfMiss 如果不在列表中是否排在后边 + * @param map 参与排序的map,map中的value值大小决定了对象的排序先后 + */ + @SuppressWarnings("unchecked") + private IndexedComparator(boolean atEndIfMiss, Map map) { + this.atEndIfMiss = atEndIfMiss; + this.map = map; + } + /** * 构造 * @@ -38,7 +55,10 @@ public class IndexedComparator implements Comparator { public IndexedComparator(boolean atEndIfMiss, T... objs) { Assert.notNull(objs, "'objs' array must not be null"); this.atEndIfMiss = atEndIfMiss; - this.array = objs; + map = new HashMap<>(1 + (int) (objs.length / 0.75)); + for (int i = 0; i < objs.length; i++) { + map.put(objs[i], i); + } } @Override @@ -47,8 +67,8 @@ public class IndexedComparator implements Comparator { final int index2 = getOrder(o2); if (index1 == index2) { - if (index1 < 0 || index1 == this.array.length) { - // 任意一个元素不在列表中, 返回原顺序 + if (index1 < 0 || index1 == this.map.size()) { + // 任意一个元素不在map中, 返回原顺序 return 1; } @@ -60,15 +80,15 @@ public class IndexedComparator implements Comparator { } /** - * 查找对象类型所在列表的位置 + * 查找对象类型所对应的顺序值,即在原列表中的顺序 * * @param object 对象 - * @return 位置,未找到位置根据{@link #atEndIfMiss}取不同值,false返回-1,否则返回列表长度 + * @return 位置,未找到位置根据{@link #atEndIfMiss}取不同值,false返回-1,否则返回map长度 */ private int getOrder(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/cn/hutool/core/comparator/IndexedComparatorTest.java b/hutool-core/src/test/java/cn/hutool/core/comparator/IndexedComparatorTest.java new file mode 100644 index 000000000..1ed188d7f --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/comparator/IndexedComparatorTest.java @@ -0,0 +1,47 @@ +package cn.hutool.core.comparator; + +import cn.hutool.core.collection.CollectionUtil; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +public class IndexedComparatorTest { + @Test + public void sortTest() { + final Object[] arr ={"a", "b", new User("9", null), "1",3,null,"2"}; + final Collection set = new HashSet<>(Arrays.asList(arr)); + + final List sortSet = CollectionUtil.sort(set, new IndexedComparator<>(arr)); + + Assert.assertEquals("a", sortSet.get(0)); + Assert.assertEquals( new User("9", null), sortSet.get(2)); + Assert.assertEquals(3, sortSet.get(4)); + Assert.assertNull(sortSet.get(5)); + } + + @Test + public void reversedTest() { + final Object[] arr ={"a", "b", new User("9", null), "1",3,null,"2"}; + final Collection set = new HashSet<>(Arrays.asList(arr)); + + final List sortSet = CollectionUtil.sort(set, new IndexedComparator<>(arr).reversed()); + + Assert.assertEquals("a", sortSet.get(6)); + Assert.assertNull(sortSet.get(1)); + Assert.assertEquals( new User("9", null), sortSet.get(4)); + Assert.assertEquals(3, sortSet.get(2)); + } + + @Data + @AllArgsConstructor + static class User{ + private String a; + private String b; + } +}