< prev index next >
src/java.base/share/classes/java/util/Comparator.java
Print this page
rev 17656 : [mq]: 8134512-provide-Alpha-Numeric-logical-Comparator
*** 28,38 ****
import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
- import java.util.Comparators;
/**
* A comparison function, which imposes a <i>total ordering</i> on some
* collection of objects. Comparators can be passed to a sort method (such
* as {@link Collections#sort(List,Comparator) Collections.sort} or {@link
--- 28,37 ----
*** 524,534 ****
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
! public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
}
--- 523,686 ----
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
! public static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
+
+ /**
+ * The returned comparator compares two character sequences as though each
+ * of them would be first transformed into a tuple of the form:
+ * <pre>{@code (A0, N0, A1, N1, ..., An-1, Nn-1, An, Nn)}</pre>
+ * where:
+ * <p>{@code A0} and {@code An} are (possibly empty) sub-sequences
+ * consisting of non-decimal-digit characters,
+ * <p>{@code A1 ... An-1} are non-empty sub-sequences consisting of
+ * non-decimal-digit characters,
+ * <p>{@code N0 ... Nn-1} are non-empty sub-sequences consisting of
+ * decimal-digit characters, and
+ * <p>{@code Nn} is a (possibly empty) sub-sequence consisting of
+ * decimal-digit characters.
+ *
+ * <p>All sub-sequences concatenated together in order as they appear in the
+ * tuple yield the original character sequence.
+ *
+ * After transformation, the tuples are compared by their elements (from
+ * left to right) so that corresponding {@code Ax} elements are compared
+ * using the provided comparator {@code alphaComparator} and {@code Nx}
+ * elements are compared as non negative decimal integers.
+ *
+ * The first pair of compared elements that is different with respect to the
+ * used comparator (either {@code alphaComparator}, or special decimal
+ * comparator) if any, provides the result produced by this comparator.
+ * The arguments are treated equal, if and only if all the subsequences,
+ * both decimal and non-decimal, compare equal.
+ *
+ * <p>For example, the following array was sorted using such comparator:
+ * <pre>{@code
+ * { "1ab", "5ab", "10ab",
+ * "a1b", "a5b", "a10b",
+ * "ab1", "ab5", "ab10" };}</pre>
+ *
+ * <p>When comparing numerical parts, an empty character sequence is
+ * considered less than any non-empty sequence of decimal digits.
+ *
+ * <p>If the numeric values of two compared character sub-sequences are
+ * equal, but their string representations have different number of leading
+ * zeroes, the comparator treats the number with less leading zeros as
+ * smaller.
+ * For example, {@code "abc 1" < "abc 01" < "abc 001"}.
+ *
+ * @apiNote For example, to sort a collection of {@code String} based on
+ * case-insensitive ordering, and treating numbers with more leading
+ * zeroes as greater, one could use
+ *
+ * <pre>{@code
+ * Comparator<String> cmp = Comparator.comparingAlphaDecimal(
+ * Comparator.comparing(CharSequence::toString,
+ * String::compareToIgnoreCase));
+ * }</pre>
+ *
+ * @implSpec To test if the given code point represents a decimal digit,
+ * the comparator checks if {@link java.lang.Character#getType(int)}
+ * returns value {@link java.lang.Character#DECIMAL_DIGIT_NUMBER}.
+ * The comparator uses {@link java.lang.Character#digit(int, int)} with
+ * the second argument set to {@code 10} to determine the numeric
+ * value of a digit represented by the given code point.
+ *
+ * @param alphaComparator the comparator that compares sub-sequences
+ * consisting of non-decimal-digits
+ * @param <T> the type of elements to be compared; normally
+ * {@link java.lang.CharSequence}
+ * @return a comparator that compares character sequences, following the
+ * rules described above
+ * @throws NullPointerException if the argument is null
+ *
+ * @since 10
+ */
+ public static <T extends CharSequence> Comparator<T>
+ comparingAlphaDecimal(Comparator<? super CharSequence> alphaComparator) {
+ return new Comparators.AlphaDecimalComparator<>(
+ Objects.requireNonNull(alphaComparator), false);
+ }
+
+ /**
+ * The returned comparator compares two character sequences as though each
+ * of them would be first transformed into a tuple of the form:
+ * <pre>{@code (A0, N0, A1, N1, ..., An-1, Nn-1, An, Nn)}</pre>
+ * where:
+ * <p>{@code A0} and {@code An} are (possibly empty) sub-sequences
+ * consisting of non-decimal-digit characters,
+ * <p>{@code A1 ... An-1} are non-empty sub-sequences consisting of
+ * non-decimal-digit characters,
+ * <p>{@code N0 ... Nn-1} are non-empty sub-sequences consisting of
+ * decimal-digit characters, and
+ * <p>{@code Nn} is a (possibly empty) sub-sequence consisting of
+ * decimal-digit characters.
+ *
+ * <p>All sub-sequences concatenated together in order as they appear in the
+ * tuple yield the original character sequence.
+ *
+ * After transformation, the tuples are compared by their elements (from
+ * left to right) so that corresponding {@code Ax} elements are compared
+ * using the provided comparator {@code alphaComparator} and {@code Nx}
+ * elements are compared as non negative decimal integers.
+ *
+ * The first pair of compared elements that is different with respect to the
+ * used comparator (either {@code alphaComparator}, or special decimal
+ * comparator) if any, provides the result produced by this comparator.
+ * The arguments are treated equal, if and only if all the subsequences,
+ * both decimal and non-decimal, compare equal.
+ *
+ * <p>For example, the following array was sorted using such comparator:
+ * <pre>{@code
+ * { "1ab", "5ab", "10ab",
+ * "a1b", "a5b", "a10b",
+ * "ab1", "ab5", "ab10" };}</pre>
+ *
+ * <p>When comparing numerical parts, an empty character sequence is
+ * considered less than any non-empty sequence of decimal digits.
+ *
+ * <p>If the numeric values of two compared character sub-sequences are
+ * equal, but their string representations have different number of leading
+ * zeroes, the comparator treats the number with more leading zeros as
+ * smaller.
+ * For example, {@code "abc 001" < "abc 01" < "abc 1"}.
+ *
+ * @apiNote For example, to sort a collection of {@code String} based on
+ * case-insensitive ordering, and treating numbers with less leading
+ * zeroes as greater, one could use
+ *
+ * <pre>{@code
+ * Comparator<String> cmp = Comparator.comparingAlphaDecimalLeadingZeroesFirst(
+ * Comparator.comparing(CharSequence::toString,
+ * String::compareToIgnoreCase));
+ * }</pre>
+ *
+ * @implSpec To test if the given code point represents a decimal digit,
+ * the comparator checks if {@link java.lang.Character#getType(int)}
+ * returns value {@link java.lang.Character#DECIMAL_DIGIT_NUMBER}.
+ * The comparator uses {@link java.lang.Character#digit(int, int)} with
+ * the second argument set to {@code 10} to determine the numeric
+ * value of a digit represented by the given code point.
+ *
+ * @param alphaComparator the comparator that compares sub-sequences
+ * consisting of non-decimal-digits
+ * @param <T> the type of elements to be compared; normally
+ * {@link java.lang.CharSequence}
+ * @return a comparator that compares character sequences, following the
+ * rules described above
+ * @throws NullPointerException if the argument is null
+ *
+ * @since 10
+ */
+ public static <T extends CharSequence> Comparator<T>
+ comparingAlphaDecimalLeadingZeroesFirst(
+ Comparator<? super CharSequence> alphaComparator) {
+ return new Comparators.AlphaDecimalComparator<>(
+ Objects.requireNonNull(alphaComparator), true);
+ }
}
< prev index next >