< 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 >