diff --git a/hutool-core/src/test/java/cn/hutool/core/comparator/ArrayIndexedComparator.java b/hutool-core/src/test/java/cn/hutool/core/comparator/ArrayIndexedComparator.java new file mode 100644 index 000000000..44bd6c929 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/comparator/ArrayIndexedComparator.java @@ -0,0 +1,75 @@ +package cn.hutool.core.comparator; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.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(T... objs) { + this(false, objs); + } + + /** + * 构造 + * + * @param atEndIfMiss 如果不在列表中是否排在后边 + * @param objs 参与排序的数组,数组的元素位置决定了对象的排序先后 + */ + @SuppressWarnings("unchecked") + public ArrayIndexedComparator(boolean atEndIfMiss, T... objs) { + Assert.notNull(objs, "'objs' array must not be null"); + this.atEndIfMiss = atEndIfMiss; + this.array = objs; + } + + @Override + public int compare(T o1, 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 0; + } + + return Integer.compare(index1, index2); + } + + /** + * 查找对象类型所在列表的位置 + * + * @param object 对象 + * @return 位置,未找到位置根据{@link #atEndIfMiss}取不同值,false返回-1,否则返回列表长度 + */ + private int getOrder(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/test/java/cn/hutool/core/comparator/IndexedComparatorTest.java b/hutool-core/src/test/java/cn/hutool/core/comparator/IndexedComparatorTest.java index 1ed188d7f..e9fef92ad 100644 --- a/hutool-core/src/test/java/cn/hutool/core/comparator/IndexedComparatorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/comparator/IndexedComparatorTest.java @@ -1,6 +1,7 @@ package cn.hutool.core.comparator; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.StopWatch; import lombok.AllArgsConstructor; import lombok.Data; import org.junit.Assert; @@ -17,7 +18,8 @@ public class IndexedComparatorTest { 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)); + + final List sortSet = CollectionUtil.sort(set, new ArrayIndexedComparator<>(arr)); Assert.assertEquals("a", sortSet.get(0)); Assert.assertEquals( new User("9", null), sortSet.get(2)); @@ -30,7 +32,7 @@ public class IndexedComparatorTest { 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()); + final List sortSet = CollectionUtil.sort(set, new ArrayIndexedComparator<>(arr).reversed()); Assert.assertEquals("a", sortSet.get(6)); Assert.assertNull(sortSet.get(1)); @@ -38,6 +40,29 @@ public class IndexedComparatorTest { Assert.assertEquals(3, sortSet.get(2)); } + @Test + public void benchMarkSortTest() { + final Object[] arr ={"a", "b", new User("9", null), "1",3,null,"2"}; + final Collection set = new HashSet<>(Arrays.asList(arr)); + + final StopWatch stopWatch = new StopWatch(); + + stopWatch.start(); + for (int i = 0; i < 10_000_000; i++) { + final List sortSet = CollectionUtil.sort(set, new IndexedComparator<>(arr)); + } + stopWatch.stop(); + System.out.println(stopWatch.prettyPrint()); + + + stopWatch.start(); + for (int i = 0; i < 10_000_000; i++) { + final List sortSet = CollectionUtil.sort(set, new ArrayIndexedComparator<>(arr)); + } + stopWatch.stop(); + System.out.println(stopWatch.prettyPrint()); + } + @Data @AllArgsConstructor static class User{