Browse Source

add InstanceComparator

Looly 5 years ago
parent
commit
a98f518c6f

+ 1 - 0
CHANGELOG.md

@@ -12,6 +12,7 @@
 * 【core  】     增加toEpochMilli方法
 * 【core  】     增加toEpochMilli方法
 * 【core  】     Validator修改isCitizenId校验(pr#1032@Github)
 * 【core  】     Validator修改isCitizenId校验(pr#1032@Github)
 * 【core  】     增加PathUtil和FileNameUtil,分离FileUtil中部分方法
 * 【core  】     增加PathUtil和FileNameUtil,分离FileUtil中部分方法
+* 【core  】     改造IndexedComparator,增加InstanceComparator
 
 
 ### Bug修复#
 ### Bug修复#
 * 【poi   】     修复ExcelBase.isXlsx方法判断问题(issue#I1S502@Gitee)
 * 【poi   】     修复ExcelBase.isXlsx方法判断问题(issue#I1S502@Gitee)

+ 35 - 11
hutool-core/src/main/java/cn/hutool/core/comparator/IndexedComparator.java

@@ -1,41 +1,65 @@
 package cn.hutool.core.comparator;
 package cn.hutool.core.comparator;
 
 
+import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ArrayUtil;
 
 
 import java.util.Comparator;
 import java.util.Comparator;
 
 
 /**
 /**
  * 按照数组的顺序正序排列,数组的元素位置决定了对象的排序先后<br>
  * 按照数组的顺序正序排列,数组的元素位置决定了对象的排序先后<br>
- * 如果参与排序的元素并不在数组中,则排序在前
- * 
- * @author looly
+ * 默认的,如果参与排序的元素并不在数组中,则排序在前(可以通过atEndIfMiss设置)
  *
  *
  * @param <T> 被排序元素类型
  * @param <T> 被排序元素类型
+ * @author looly
  * @since 4.1.5
  * @since 4.1.5
  */
  */
 public class IndexedComparator<T> implements Comparator<T> {
 public class IndexedComparator<T> implements Comparator<T> {
 
 
+	private final boolean atEndIfMiss;
 	private final T[] array;
 	private final T[] array;
 
 
 	/**
 	/**
 	 * 构造
 	 * 构造
-	 * 
+	 *
 	 * @param objs 参与排序的数组,数组的元素位置决定了对象的排序先后
 	 * @param objs 参与排序的数组,数组的元素位置决定了对象的排序先后
 	 */
 	 */
 	@SuppressWarnings("unchecked")
 	@SuppressWarnings("unchecked")
 	public IndexedComparator(T... objs) {
 	public IndexedComparator(T... objs) {
+		this(false, objs);
+	}
+
+	/**
+	 * 构造
+	 *
+	 * @param atEndIfMiss 如果不在列表中是否排在后边
+	 * @param objs        参与排序的数组,数组的元素位置决定了对象的排序先后
+	 */
+	@SuppressWarnings("unchecked")
+	public IndexedComparator(boolean atEndIfMiss, T... objs) {
+		Assert.notNull(objs, "'objs' array must not be null");
+		this.atEndIfMiss = atEndIfMiss;
 		this.array = objs;
 		this.array = objs;
 	}
 	}
 
 
 	@Override
 	@Override
 	public int compare(T o1, T o2) {
 	public int compare(T o1, T o2) {
-		final int index1 = ArrayUtil.indexOf(array, o1);
-		final int index2 = ArrayUtil.indexOf(array, o2);
-		if(index1 == index2) {
-			//位置相同使用自然排序
-			return CompareUtil.compare(o1, o2, true);
-		}
-		return index1 < index2 ? -1 : 1;
+		final int index1 = getOrder(o1);
+		final int index2 = getOrder(o2);
+
+		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;
+	}
 }
 }

+ 83 - 0
hutool-core/src/main/java/cn/hutool/core/comparator/InstanceComparator.java

@@ -0,0 +1,83 @@
+/*
+ * Copyright 2002-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package cn.hutool.core.comparator;
+
+import cn.hutool.core.lang.Assert;
+
+import java.util.Comparator;
+
+/**
+ * 按照指定类型顺序排序,对象顺序取决于对象对应的类在数组中的位置。
+ *
+ * <p>如果对比的两个对象类型相同,返回{@code 0},默认如果对象类型不在列表中,则排序在前</p>
+ * <p>此类来自Spring,有所改造</p>
+ *
+ * @param <T> 用于比较的对象类型
+ * @author Phillip Webb
+ * @since 5.4.1
+ */
+public class InstanceComparator<T> implements Comparator<T> {
+
+	private final boolean atEndIfMiss;
+	private final Class<?>[] instanceOrder;
+
+	/**
+	 * 构造
+	 *
+	 * @param instanceOrder 用于比较排序的对象类型数组,排序按照数组位置排序
+	 */
+	public InstanceComparator(Class<?>... instanceOrder) {
+		this(false, instanceOrder);
+	}
+
+	/**
+	 * 构造
+	 *
+	 * @param atEndIfMiss   如果不在列表中是否排在后边
+	 * @param instanceOrder 用于比较排序的对象类型数组,排序按照数组位置排序
+	 */
+	public InstanceComparator(boolean atEndIfMiss, Class<?>... instanceOrder) {
+		Assert.notNull(instanceOrder, "'instanceOrder' array must not be null");
+		this.atEndIfMiss = atEndIfMiss;
+		this.instanceOrder = instanceOrder;
+	}
+
+
+	@Override
+	public int compare(T o1, T o2) {
+		int i1 = getOrder(o1);
+		int i2 = getOrder(o2);
+		return Integer.compare(i1, i2);
+	}
+
+	/**
+	 * 查找对象类型所在列表的位置
+	 *
+	 * @param object 对象
+	 * @return 位置,未找到位置根据{@link #atEndIfMiss}取不同值,false返回-1,否则返回列表长度
+	 */
+	private int getOrder(T object) {
+		if (object != null) {
+			for (int i = 0; i < this.instanceOrder.length; i++) {
+				if (this.instanceOrder[i].isInstance(object)) {
+					return i;
+				}
+			}
+		}
+		return this.atEndIfMiss ? this.instanceOrder.length : -1;
+	}
+}

+ 1 - 1
hutool-core/src/main/java/cn/hutool/core/lang/UUID.java

@@ -40,7 +40,7 @@ import java.util.Random;
  *
  *
  * @since 4.1.11
  * @since 4.1.11
  */
  */
-public final class UUID implements java.io.Serializable, Comparable<UUID> {
+public class UUID implements java.io.Serializable, Comparable<UUID> {
 	private static final long serialVersionUID = -1185015143654744140L;
 	private static final long serialVersionUID = -1185015143654744140L;
 
 
 	/**
 	/**