|
@@ -11,30 +11,31 @@ import java.util.Comparator;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
import java.util.Objects;
|
|
|
import java.util.function.Predicate;
|
|
import java.util.function.Predicate;
|
|
|
-import java.util.function.Supplier;
|
|
|
|
|
|
|
|
|
|
|
|
+import lombok.experimental.UtilityClass;
|
|
|
import net.ranides.assira.collection.IntComparator;
|
|
import net.ranides.assira.collection.IntComparator;
|
|
|
import net.ranides.assira.collection.maps.WeakIdentMap;
|
|
import net.ranides.assira.collection.maps.WeakIdentMap;
|
|
|
-import net.ranides.assira.functional.FunctionUtils;
|
|
|
|
|
-import net.ranides.assira.functional.Functions;
|
|
|
|
|
-import net.ranides.assira.reflection.*;
|
|
|
|
|
import net.ranides.assira.text.LexicalCast;
|
|
import net.ranides.assira.text.LexicalCast;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Static methods for comparing objects, comparisons are null-safe.
|
|
|
|
|
+ */
|
|
|
@SuppressWarnings({
|
|
@SuppressWarnings({
|
|
|
"PMD.ShortVar",
|
|
"PMD.ShortVar",
|
|
|
"PMD.ShortMethodName"
|
|
"PMD.ShortMethodName"
|
|
|
})
|
|
})
|
|
|
-public final class CompareUtils {
|
|
|
|
|
|
|
+@UtilityClass
|
|
|
|
|
+public class CompareUtils {
|
|
|
|
|
|
|
|
@SuppressWarnings({"rawtypes"})
|
|
@SuppressWarnings({"rawtypes"})
|
|
|
- private static final Comparator AUTO_COMPARATOR = new NComparator();
|
|
|
|
|
-
|
|
|
|
|
- private CompareUtils() { }
|
|
|
|
|
|
|
+ private static final Comparator AUTO_COMPARATOR = new NaturalComparator();
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Compares passed arguments usig Object#equals method.
|
|
* Compares passed arguments usig Object#equals method.
|
|
|
- * <div class="message-note">{@code null} safe method</div>
|
|
|
|
|
|
|
+ *
|
|
|
|
|
+ * Method is null-safe.
|
|
|
|
|
+ *
|
|
|
* @param a a
|
|
* @param a a
|
|
|
* @param b b
|
|
* @param b b
|
|
|
* @return bool
|
|
* @return bool
|
|
@@ -47,6 +48,9 @@ public final class CompareUtils {
|
|
|
/**
|
|
/**
|
|
|
* If both arguments are numbers ({@code instanceof Number}) then compares
|
|
* If both arguments are numbers ({@code instanceof Number}) then compares
|
|
|
* with specified precision. Use standard comparison otherwise.
|
|
* with specified precision. Use standard comparison otherwise.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Method is null-safe.
|
|
|
|
|
+ *
|
|
|
* @param a a
|
|
* @param a a
|
|
|
* @param b b
|
|
* @param b b
|
|
|
* @param precision precision
|
|
* @param precision precision
|
|
@@ -62,6 +66,8 @@ public final class CompareUtils {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Compares numbers with specified precision.
|
|
* Compares numbers with specified precision.
|
|
|
|
|
+ * Method is null-safe.
|
|
|
|
|
+ *
|
|
|
* @param a a
|
|
* @param a a
|
|
|
* @param b b
|
|
* @param b b
|
|
|
* @param precision precision
|
|
* @param precision precision
|
|
@@ -70,16 +76,44 @@ public final class CompareUtils {
|
|
|
public static boolean equals(Number a, Number b, double precision) {
|
|
public static boolean equals(Number a, Number b, double precision) {
|
|
|
return (null==a) ? (null==b) : (null!=b) && (Math.abs(a.doubleValue() - b.doubleValue()) <= precision);
|
|
return (null==a) ? (null==b) : (null!=b) && (Math.abs(a.doubleValue() - b.doubleValue()) <= precision);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Compares two values using natural comparator.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Method is null-safe.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param value1 value1
|
|
|
|
|
+ * @param value2 value2
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return int
|
|
|
|
|
+ */
|
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
|
public static <T> int cmp(T value1, T value2) {
|
|
public static <T> int cmp(T value1, T value2) {
|
|
|
return AUTO_COMPARATOR.compare(value1, value2);
|
|
return AUTO_COMPARATOR.compare(value1, value2);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Compares two integer values.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param value1 value1
|
|
|
|
|
+ * @param value2 value2
|
|
|
|
|
+ * @return int
|
|
|
|
|
+ */
|
|
|
public static int cmp(int value1, int value2) {
|
|
public static int cmp(int value1, int value2) {
|
|
|
return value1 - value2;
|
|
return value1 - value2;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Compares two values using provided comparator.
|
|
|
|
|
+ * Comparator is optional.
|
|
|
|
|
+ * Method is null-safe only if provided comparator supports null values.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param comparator comparator
|
|
|
|
|
+ * @param value1 value1
|
|
|
|
|
+ * @param value2 value2
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return int
|
|
|
|
|
+ */
|
|
|
public static <T> int cmp(Comparator<? super T> comparator, T value1, T value2) {
|
|
public static <T> int cmp(Comparator<? super T> comparator, T value1, T value2) {
|
|
|
if(null != comparator ) {
|
|
if(null != comparator ) {
|
|
|
return comparator.compare(value1, value2);
|
|
return comparator.compare(value1, value2);
|
|
@@ -87,7 +121,16 @@ public final class CompareUtils {
|
|
|
return cmp(value1, value2);
|
|
return cmp(value1, value2);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Compares two values using provided comparator.
|
|
|
|
|
+ * Comparator is optional.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param comparator comparator
|
|
|
|
|
+ * @param value1 value1
|
|
|
|
|
+ * @param value2 value2
|
|
|
|
|
+ * @return int
|
|
|
|
|
+ */
|
|
|
public static int cmp(IntComparator comparator, int value1, int value2) {
|
|
public static int cmp(IntComparator comparator, int value1, int value2) {
|
|
|
if(null != comparator ) {
|
|
if(null != comparator ) {
|
|
|
return comparator.compare(value1, value2);
|
|
return comparator.compare(value1, value2);
|
|
@@ -96,7 +139,19 @@ public final class CompareUtils {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns lower non-null value.
|
|
|
|
|
+ * Uses provided comparator for comparing objects.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Method is null-safe.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param comparator comparator
|
|
|
|
|
+ * @param value1 value1
|
|
|
|
|
+ * @param value2 value2
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return value
|
|
|
|
|
+ */
|
|
|
public static <T> T lower(Comparator<? super T> comparator, T value1, T value2) {
|
|
public static <T> T lower(Comparator<? super T> comparator, T value1, T value2) {
|
|
|
if(null == value1) {
|
|
if(null == value1) {
|
|
|
return value2;
|
|
return value2;
|
|
@@ -106,11 +161,32 @@ public final class CompareUtils {
|
|
|
}
|
|
}
|
|
|
return cmp(comparator, value1, value2) < 0 ? value1 : value2;
|
|
return cmp(comparator, value1, value2) < 0 ? value1 : value2;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns lower int value.
|
|
|
|
|
+ * Uses provided comparator for comparing objects.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param comparator comparator
|
|
|
|
|
+ * @param value1 value1
|
|
|
|
|
+ * @param value2 value2
|
|
|
|
|
+ * @return value
|
|
|
|
|
+ */
|
|
|
public static int lower(IntComparator comparator, int value1, int value2) {
|
|
public static int lower(IntComparator comparator, int value1, int value2) {
|
|
|
return cmp(comparator, value1, value2) < 0 ? value1 : value2;
|
|
return cmp(comparator, value1, value2) < 0 ? value1 : value2;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns higher non-null value.
|
|
|
|
|
+ * Uses provided comparator for comparing objects.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Method is null-safe.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param comparator comparator
|
|
|
|
|
+ * @param value1 value1
|
|
|
|
|
+ * @param value2 value2
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return value
|
|
|
|
|
+ */
|
|
|
public static <T> T higher(Comparator<? super T> comparator, T value1, T value2) {
|
|
public static <T> T higher(Comparator<? super T> comparator, T value1, T value2) {
|
|
|
if(null == value1) {
|
|
if(null == value1) {
|
|
|
return value2;
|
|
return value2;
|
|
@@ -120,11 +196,29 @@ public final class CompareUtils {
|
|
|
}
|
|
}
|
|
|
return cmp(comparator, value1, value2) > 0 ? value1 : value2;
|
|
return cmp(comparator, value1, value2) > 0 ? value1 : value2;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns higher int value.
|
|
|
|
|
+ * Uses provided comparator for comparing objects.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param comparator comparator
|
|
|
|
|
+ * @param value1 value1
|
|
|
|
|
+ * @param value2 value2
|
|
|
|
|
+ * @return value
|
|
|
|
|
+ */
|
|
|
public static int higher(IntComparator comparator, int value1, int value2) {
|
|
public static int higher(IntComparator comparator, int value1, int value2) {
|
|
|
return cmp(comparator, value1, value2) > 0 ? value1 : value2;
|
|
return cmp(comparator, value1, value2) > 0 ? value1 : value2;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns predicate which returns true if tested object is equal to provided one.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Method is null-safe.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param a a
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return predicate
|
|
|
|
|
+ */
|
|
|
public static <T> Predicate<T> predicate(T a) {
|
|
public static <T> Predicate<T> predicate(T a) {
|
|
|
if(null == a) {
|
|
if(null == a) {
|
|
|
return b -> b==null;
|
|
return b -> b==null;
|
|
@@ -132,12 +226,29 @@ public final class CompareUtils {
|
|
|
return b -> a.equals(b);
|
|
return b -> a.equals(b);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns natural comparator.
|
|
|
|
|
+ * Comparator assumes that both objects are Comparable.
|
|
|
|
|
+ * It uses Comparable interface if objects are compatible.
|
|
|
|
|
+ * If not, it uses LexicalCast to normalize types.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return comparator
|
|
|
|
|
+ */
|
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
|
public static <T> Comparator<T> comparator() {
|
|
public static <T> Comparator<T> comparator() {
|
|
|
return AUTO_COMPARATOR;
|
|
return AUTO_COMPARATOR;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns natural comparator for provided type.
|
|
|
|
|
+ * It could return optimized version for some types, for example for "int".
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param type type
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return comparator
|
|
|
|
|
+ */
|
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
|
public static <T> Comparator<T> comparator(Class<?> type) {
|
|
public static <T> Comparator<T> comparator(Class<?> type) {
|
|
|
if(int.class.equals(type) || Integer.class.equals(type)) {
|
|
if(int.class.equals(type) || Integer.class.equals(type)) {
|
|
@@ -147,6 +258,13 @@ public final class CompareUtils {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns reversed comparator
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param comparator comparator
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return comparator
|
|
|
|
|
+ */
|
|
|
public static <T> Comparator<T> reversed(Comparator<T> comparator) {
|
|
public static <T> Comparator<T> reversed(Comparator<T> comparator) {
|
|
|
return comparator.reversed();
|
|
return comparator.reversed();
|
|
|
}
|
|
}
|
|
@@ -162,12 +280,15 @@ public final class CompareUtils {
|
|
|
* COMPARATOR.compare(a,b) = -COMPARATOR.compare(b,a) != 0
|
|
* COMPARATOR.compare(a,b) = -COMPARATOR.compare(b,a) != 0
|
|
|
*
|
|
*
|
|
|
* This comparator is useful, if you want to store duplicates in standard TreeSets and TreeMaps
|
|
* This comparator is useful, if you want to store duplicates in standard TreeSets and TreeMaps
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param <T> T
|
|
|
|
|
+ * @return comparator
|
|
|
*/
|
|
*/
|
|
|
public static <T> Comparator<T> identity() {
|
|
public static <T> Comparator<T> identity() {
|
|
|
- return new IComparator<>();
|
|
|
|
|
|
|
+ return new IdentComparator<>();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static final class IComparator<T> implements Comparator<T>, Serializable {
|
|
|
|
|
|
|
+ private static final class IdentComparator<T> implements Comparator<T>, Serializable {
|
|
|
|
|
|
|
|
private final Map<T, Integer> map = new WeakIdentMap<>();
|
|
private final Map<T, Integer> map = new WeakIdentMap<>();
|
|
|
|
|
|
|
@@ -185,7 +306,7 @@ public final class CompareUtils {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static final class NComparator implements Comparator<Comparable>, Serializable {
|
|
|
|
|
|
|
+ private static final class NaturalComparator implements Comparator<Comparable>, Serializable {
|
|
|
|
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
|
|