All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java8.util.Comparators Maven / Gradle / Ivy

Go to download

streamsupport is a backport of the Java 8 java.util.function (functional interfaces) and java.util.stream (streams) API for Java 6 / 7 and Android developers

There is a newer version: 1.7.4
Show newest version
/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java8.util;

import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;

import java8.lang.Integers;
import java8.lang.Longs;
import java8.util.Objects;
import java8.util.function.Function;
import java8.util.function.ToIntFunction;
import java8.util.function.ToLongFunction;
import java8.util.function.ToDoubleFunction;

/**
 * A place for static default implementations of the new Java 8
 * default interface methods and static interface methods in the
 * {@link Comparator} interface. 
 */
public final class Comparators {
    /**
     * Compares {@link Comparable} objects in natural order.
     *
     * @see Comparable
     */
    private enum NaturalOrderComparator implements Comparator> {
        INSTANCE;

        @Override
        public int compare(Comparable c1, Comparable c2) {
            return c1.compareTo(c2);
        }

        public Comparator> reversed() {
            return Comparators.reverseOrder();
        }
    }

    /**
     * Null-friendly comparators
     */
    private static final class NullComparator implements Comparator, Serializable {
        private static final long serialVersionUID = -7569533591570686392L;
        private final boolean nullFirst;
        // if null, non-null Ts are considered equal
        private final Comparator real;

        @SuppressWarnings("unchecked")
        NullComparator(boolean nullFirst, Comparator real) {
            this.nullFirst = nullFirst;
            this.real = (Comparator) real;
        }

        @Override
        public int compare(T a, T b) {
            if (a == null) {
                return (b == null) ? 0 : (nullFirst ? -1 : 1);
            } else if (b == null) {
                return nullFirst ? 1: -1;
            } else {
                return (real == null) ? 0 : real.compare(a, b);
            }
        }

        public Comparator thenComparing(Comparator other) {
            Objects.requireNonNull(other);
            return new NullComparator(nullFirst, real == null ? other : Comparators.thenComparing(real, other));
        }

        public Comparator reversed() {
            return new NullComparator(!nullFirst, real == null ? null : Collections.reverseOrder(real));
        }
    }

    /**
     * Returns a comparator that imposes the reverse of the natural
     * ordering.
     *
     * 

The returned comparator is serializable and throws {@link * NullPointerException} when comparing {@code null}. * * @param the {@link Comparable} type of element to be compared * @return a comparator that imposes the reverse of the natural * ordering on {@code Comparable} objects. * @see Comparable * @since 1.8 */ public static > Comparator reverseOrder() { return Collections.reverseOrder(); } /** * Returns a comparator that compares {@link Comparable} objects in natural * order. * *

The returned comparator is serializable and throws {@link * NullPointerException} when comparing {@code null}. * * @param the {@link Comparable} type of element to be compared * @return a comparator that imposes the natural ordering on {@code * Comparable} objects. * @see Comparable * @since 1.8 */ @SuppressWarnings("unchecked") public static > Comparator naturalOrder() { return (Comparator) Comparators.NaturalOrderComparator.INSTANCE; } /** * Accepts a function that extracts a sort key from a type {@code T}, and * returns a {@code Comparator} that compares by that sort key using * the specified {@link Comparator}. * *

The returned comparator is serializable if the specified function * and comparator are both serializable. * *

API Note:
* For example, to obtain a {@code Comparator} that compares {@code * Person} objects by their last name ignoring case differences, * *

{@code
     *     Comparator cmp = Comparators.comparing(
     *             Person::getLastName,
     *             String.CASE_INSENSITIVE_ORDER);
     * }
* * @param the type of element to be compared * @param the type of the sort key * @param keyExtractor the function used to extract the sort key * @param keyComparator the {@code Comparator} used to compare the sort key * @return a comparator that compares by an extracted key using the * specified {@code Comparator} * @throws NullPointerException if either argument is null * @since 1.8 */ public static Comparator comparing( Function keyExtractor, Comparator keyComparator) { Objects.requireNonNull(keyExtractor); Objects.requireNonNull(keyComparator); return (Comparator & Serializable) (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1), keyExtractor.apply(c2)); } /** * Accepts a function that extracts a {@link java.lang.Comparable * Comparable} sort key from a type {@code T}, and returns a {@code * Comparator} that compares by that sort key. * *

The returned comparator is serializable if the specified function * is also serializable. * *

API Note:
* For example, to obtain a {@code Comparator} that compares {@code * Person} objects by their last name, * *

{@code
     *     Comparator byLastName = Comparators.comparing(Person::getLastName);
     * }
* * @param the type of element to be compared * @param the type of the {@code Comparable} sort key * @param keyExtractor the function used to extract the {@link * Comparable} sort key * @return a comparator that compares by an extracted key * @throws NullPointerException if the argument is null * @since 1.8 */ public static > Comparator comparing( Function keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); } /** * Accepts a function that extracts an {@code int} sort key from a type * {@code T}, and returns a {@code Comparator} that compares by that * sort key. * *

The returned comparator is serializable if the specified function * is also serializable. * * @param the type of element to be compared * @param keyExtractor the function used to extract the integer sort key * @return a comparator that compares by an extracted key * @see #comparing(Function) * @throws NullPointerException if the argument is null * @since 1.8 */ public static Comparator comparingInt(ToIntFunction keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator & Serializable) (c1, c2) -> Integers.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2)); } /** * Accepts a function that extracts a {@code long} sort key from a type * {@code T}, and returns a {@code Comparator} that compares by that * sort key. * *

The returned comparator is serializable if the specified function is * also serializable. * * @param the type of element to be compared * @param keyExtractor the function used to extract the long sort key * @return a comparator that compares by an extracted key * @see #comparing(Function) * @throws NullPointerException if the argument is null * @since 1.8 */ public static Comparator comparingLong(ToLongFunction keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator & Serializable) (c1, c2) -> Longs.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2)); } /** * Accepts a function that extracts a {@code double} sort key from a type * {@code T}, and returns a {@code Comparator} that compares by that * sort key. * *

The returned comparator is serializable if the specified function * is also serializable. * * @param the type of element to be compared * @param keyExtractor the function used to extract the double sort key * @return a comparator that compares by an extracted key * @see #comparing(Function) * @throws NullPointerException if the argument is null * @since 1.8 */ public static Comparator comparingDouble(ToDoubleFunction keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator & Serializable) (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2)); } /** * Returns a lexicographic-order comparator with another comparator. * If the {@code this_} {@code Comparator} considers two elements equal, i.e. * {@code compare(a, b) == 0}, {@code other} is used to determine the order. * *

The returned comparator is serializable if the specified comparators * are also serializable. * *

API Note:
* For example, to sort a collection of {@code String} based on the length * and then case-insensitive natural ordering, the comparators can be * composed using following code, * *

{@code
     *     Comparator cmp = Comparators.thenComparing(Comparators.comparingInt(String::length),
     *                        String.CASE_INSENSITIVE_ORDER);
     * }
* * @param the type of objects that may be compared by the passed comparators * @param this_ the comparator to be used first * @param other the other comparator to be used when the {@code this_} comparator * compares two objects that are equal. * @return a lexicographic-order comparator composed of the {@code this_} and then the * other comparator * @throws NullPointerException if {@code this_} is null. * @throws NullPointerException if {@code other} is null. * @since 1.8 */ public static Comparator thenComparing(Comparator this_, Comparator other) { Objects.requireNonNull(this_); Objects.requireNonNull(other); if (this_ instanceof NullComparator) { return ((NullComparator) this_).thenComparing(other); } return (Comparator & Serializable) (c1, c2) -> { int res = this_.compare(c1, c2); return (res != 0) ? res : other.compare(c1, c2); }; } /** * Returns a lexicographic-order comparator with a function that * extracts a key to be compared with the given {@code Comparator}. * *

Implementation Requirements:
This default implementation behaves as if {@code * thenComparing(this_, comparing(keyExtractor, keyComparator))}. * * @param the type of objects that may be compared by the {@code this_} comparator * @param the type of the sort key * @param this_ the comparator to be used first * @param keyExtractor the function used to extract the sort key * @param keyComparator the {@code Comparator} used to compare the sort key * @return a lexicographic-order comparator composed of the {@code this_} comparator * and then comparing on the key extracted by the keyExtractor function * @throws NullPointerException if either argument is null. * @see #comparing(Function, Comparator) * @see #thenComparing(Comparator, Comparator) * @since 1.8 */ public static Comparator thenComparing( Comparator this_, Function keyExtractor, Comparator keyComparator) { return thenComparing(this_, comparing(keyExtractor, keyComparator)); } /** * Returns a lexicographic-order comparator with a function that * extracts a {@code Comparable} sort key. * *

Implementation Requirements:
This default implementation behaves as if {@code * thenComparing(this_, comparing(keyExtractor))}. * * @param the type of objects that may be compared by the {@code this_} comparator * @param the type of the {@link Comparable} sort key * @param this_ the comparator to be used first * @param keyExtractor the function used to extract the {@link * Comparable} sort key * @return a lexicographic-order comparator composed of {@code this_} and then the * {@link Comparable} sort key. * @throws NullPointerException if either argument is null. * @see #comparing(Function) * @see #thenComparing(Comparator, Comparator) * @since 1.8 */ public static > Comparator thenComparing( Comparator this_, Function keyExtractor) { return thenComparing(this_, comparing(keyExtractor)); } /** * Returns a lexicographic-order comparator with a function that * extracts a {@code int} sort key. * *

Implementation Requirements:
This default implementation behaves as if {@code * thenComparing(this_, comparingInt(keyExtractor))}. * * @param the type of objects that may be compared by the {@code this_} comparator * @param this_ the comparator to be used first * @param keyExtractor the function used to extract the integer sort key * @return a lexicographic-order comparator composed of {@code this_} and then the * {@code int} sort key * @throws NullPointerException if either argument is null. * @see #comparingInt(ToIntFunction) * @see #thenComparing(Comparator, Comparator) * @since 1.8 */ public static Comparator thenComparingInt(Comparator this_, ToIntFunction keyExtractor) { return thenComparing(this_, comparingInt(keyExtractor)); } /** * Returns a lexicographic-order comparator with a function that * extracts a {@code long} sort key. * *

Implementation Requirements:
This default implementation behaves as if {@code * thenComparing(this_, comparingLong(keyExtractor))}. * * @param the type of objects that may be compared by the {@code this_} comparator * @param this_ the comparator to be used first * @param keyExtractor the function used to extract the long sort key * @return a lexicographic-order comparator composed of {@code this_} and then the * {@code long} sort key * @throws NullPointerException if either argument is null. * @see #comparingLong(ToLongFunction) * @see #thenComparing(Comparator, Comparator) * @since 1.8 */ public static Comparator thenComparingLong(Comparator this_, ToLongFunction keyExtractor) { return thenComparing(this_, comparingLong(keyExtractor)); } /** * Returns a lexicographic-order comparator with a function that * extracts a {@code double} sort key. * *

Implementation Requirements:
This default implementation behaves as if {@code * thenComparing(this_, comparingDouble(keyExtractor))}. * * @param the type of objects that may be compared by the {@code this_} comparator * @param this_ the comparator to be used first * @param keyExtractor the function used to extract the double sort key * @return a lexicographic-order comparator composed of {@code this_} and then the * {@code double} sort key * @throws NullPointerException if either argument is null. * @see #comparingDouble(ToDoubleFunction) * @see #thenComparing(Comparator, Comparator) * @since 1.8 */ public static Comparator thenComparingDouble(Comparator this_, ToDoubleFunction keyExtractor) { return thenComparing(this_, comparingDouble(keyExtractor)); } /** * Returns a comparator that imposes the reverse ordering of the * passed {@code comparator}. * * @param the type of objects that may be compared by the comparator argument * @param comparator the comparator whose ordering needs to be reversed * @return a comparator that imposes the reverse ordering of the * passed {@code comparator}. * @since 1.8 */ public static Comparator reversed(Comparator comparator) { if (comparator instanceof NullComparator) { return ((NullComparator) comparator).reversed(); } return Collections.reverseOrder(comparator); } /** * Returns a null-friendly comparator that considers {@code null} to be * less than non-null. When both are {@code null}, they are considered * equal. If both are non-null, the specified {@code Comparator} is used * to determine the order. If the specified comparator is {@code null}, * then the returned comparator considers all non-null values to be equal. * *

The returned comparator is serializable if the specified comparator * is serializable. * * @param the type of the elements to be compared * @param comparator a {@code Comparator} for comparing non-null values * @return a comparator that considers {@code null} to be less than * non-null, and compares non-null objects with the supplied * {@code Comparator}. * @since 1.8 */ public static Comparator nullsFirst(Comparator comparator) { return new Comparators.NullComparator<>(true, comparator); } /** * Returns a null-friendly comparator that considers {@code null} to be * greater than non-null. When both are {@code null}, they are considered * equal. If both are non-null, the specified {@code Comparator} is used * to determine the order. If the specified comparator is {@code null}, * then the returned comparator considers all non-null values to be equal. * *

The returned comparator is serializable if the specified comparator * is serializable. * * @param the type of the elements to be compared * @param comparator a {@code Comparator} for comparing non-null values * @return a comparator that considers {@code null} to be greater than * non-null, and compares non-null objects with the supplied * {@code Comparator}. * @since 1.8 */ public static Comparator nullsLast(Comparator comparator) { return new Comparators.NullComparator<>(false, comparator); } private Comparators() { } }