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

com.landawn.abacus.util.Comparators Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

The newest version!
/*
 * Copyright (c) 2017, Haiyang Li.
 *
 * 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 com.landawn.abacus.util;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.util.Builder.ComparisonBuilder;
import com.landawn.abacus.util.function.ToBooleanFunction;
import com.landawn.abacus.util.function.ToByteFunction;
import com.landawn.abacus.util.function.ToCharFunction;
import com.landawn.abacus.util.function.ToFloatFunction;
import com.landawn.abacus.util.function.ToShortFunction;

/**
 *
 * Factory utility class for Comparator.
 *
 *
 */
public final class Comparators {

    @SuppressWarnings("rawtypes")
    static final Comparator NULL_FIRST_COMPARATOR = (a, b) -> a == null ? (b == null ? 0 : -1) : (b == null ? 1 : a.compareTo(b));

    @SuppressWarnings("rawtypes")
    static final Comparator NULL_FIRST_REVERSED_ORDER = (a, b) -> a == null ? (b == null ? 0 : -1) : (b == null ? 1 : b.compareTo(a));

    @SuppressWarnings("rawtypes")
    static final Comparator NULL_LAST_COMPARATOR = (a, b) -> a == null ? (b == null ? 0 : 1) : (b == null ? -1 : a.compareTo(b));

    @SuppressWarnings("rawtypes")
    static final Comparator NULL_LAST_REVERSED_ORDER = (a, b) -> a == null ? (b == null ? 0 : 1) : (b == null ? -1 : b.compareTo(a));

    @SuppressWarnings("rawtypes")
    static final Comparator NATURAL_ORDER = NULL_FIRST_COMPARATOR;

    // It's reversed order of NATURAL_ORDER and null last
    @SuppressWarnings("rawtypes")
    static final Comparator REVERSED_ORDER = NULL_LAST_REVERSED_ORDER;

    static final Comparator COMPARING_IGNORE_CASE = (a, b) -> a == null ? (b == null ? 0 : -1) : (b == null ? 1 : a.compareToIgnoreCase(b));

    static final Comparator COMPARING_BY_LENGTH = Comparator.comparingInt(a -> a == null ? 0 : a.length());

    static final Comparator COMPARING_BY_ARRAY_LENGTH = Comparator.comparingInt(a -> a == null ? 0 : Array.getLength(a));

    @SuppressWarnings("rawtypes")
    static final Comparator COMPARING_BY_SIZE = Comparator.comparingInt(a -> a == null ? 0 : a.size());

    @SuppressWarnings("rawtypes")
    static final Comparator COMPARING_BY_MAP_SIZE = Comparator.comparingInt(a -> a == null ? 0 : a.size());

    public static final Comparator BOOLEAN_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            if (a[i] != b[i]) {
                return a[i] ? 1 : -1;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    public static final Comparator CHAR_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            if (a[i] != b[i]) {
                return a[i] > b[i] ? 1 : -1;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    public static final Comparator BYTE_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            if (a[i] != b[i]) {
                return a[i] > b[i] ? 1 : -1;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    public static final Comparator SHORT_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            if (a[i] != b[i]) {
                return a[i] > b[i] ? 1 : -1;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    public static final Comparator INT_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            if (a[i] != b[i]) {
                return a[i] > b[i] ? 1 : -1;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    public static final Comparator LONG_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            if (a[i] != b[i]) {
                return a[i] > b[i] ? 1 : -1;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    public static final Comparator FLOAT_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);
        int result = 0;

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            result = Float.compare(a[i], b[i]);

            if (result != 0) {
                return result;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    public static final Comparator DOUBLE_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);
        int result = 0;

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            result = Double.compare(a[i], b[i]);

            if (result != 0) {
                return result;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    public static final Comparator OBJECT_ARRAY_COMPARATOR = (a, b) -> {
        final int lenA = N.len(a);
        final int lenB = N.len(b);
        int result = 0;

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            result = NATURAL_ORDER.compare(a[i], b[i]);

            if (result != 0) {
                return result;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    @SuppressWarnings("rawtypes")
    public static final Comparator COLLECTION_COMPARATOR = (a, b) -> {
        if (N.isEmpty(a)) {
            return N.isEmpty(b) ? 0 : -1;
        } else if (N.isEmpty(b)) {
            return 1;
        }

        final Iterator iterA = a.iterator();
        final Iterator iterB = b.iterator();

        final int lenA = N.size(a);
        final int lenB = N.size(b);
        int result = 0;

        for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) {
            result = NATURAL_ORDER.compare(iterA.next(), iterB.next());

            if (result != 0) {
                return result;
            }
        }

        return NATURAL_ORDER.compare(lenA, lenB);
    };

    private Comparators() {
        // Utility class.
    }

    /**
     * Returns a comparator that compares {@code Comparable} objects in their natural order (where {@code null} is minimum).
     * 
* Same as {@code nullsFirst()}. * * @param the type of the objects being compared * @return a comparator that compares {@code Comparable} objects in their natural order * @see #nullsFirst() */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static Comparator naturalOrder() { return NATURAL_ORDER; } /** * Returns a comparator that compares {@code Comparable} objects in their natural order (where {@code null} is minimum). *
* Same as {@code naturalOrder()}. * * @param the type of the objects being compared * @return a comparator that compares {@code Comparable} objects in their natural order * @see #naturalOrder() */ @SuppressWarnings("rawtypes") public static Comparator nullsFirst() { return (Comparator) NULL_FIRST_COMPARATOR; } /** * * @param * @param cmp * @return */ public static Comparator nullsFirst(final Comparator cmp) { if (cmp == null || cmp == NULL_FIRST_COMPARATOR) { // NOSONAR return (Comparator) NULL_FIRST_COMPARATOR; } return (a, b) -> a == null ? (b == null ? 0 : -1) : (b == null ? 1 : cmp.compare(a, b)); } /** * Comparing the key/value extracted by {@code keyExtractor} by {@code nullsFirst()} comparator. * * @param * @param keyExtractor * @return * @throws IllegalArgumentException * @see #comparingByIfNotNullOrElseNullsFirst(Function) * @see #comparingByIfNotNullOrElseNullsLast(Function) */ public static Comparator nullsFirstBy(@SuppressWarnings("rawtypes") final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> NULL_FIRST_COMPARATOR.compare(keyExtractor.apply(a), keyExtractor.apply(b)); } @SuppressWarnings("rawtypes") private static final Comparator NULLS_FIRST_OR_ELSE_EQUAL = (a, b) -> a == null ? (b == null ? 0 : -1) : (b == null ? 1 : 0); /** * * @param * @return */ @Beta public static Comparator nullsFirstOrElseEqual() { return NULLS_FIRST_OR_ELSE_EQUAL; } /** * * @param * @return */ @SuppressWarnings("rawtypes") public static Comparator nullsLast() { return (Comparator) NULL_LAST_COMPARATOR; } /** * * @param * @param cmp * @return */ public static Comparator nullsLast(final Comparator cmp) { if (cmp == null || cmp == NULL_LAST_COMPARATOR) { // NOSONAR return (Comparator) NULL_LAST_COMPARATOR; } return (a, b) -> a == null ? (b == null ? 0 : 1) : (b == null ? -1 : cmp.compare(a, b)); } @SuppressWarnings("rawtypes") private static final Comparator NULLS_LAST_OR_ELSE_EQUAL = (a, b) -> a == null ? (b == null ? 0 : 1) : (b == null ? -1 : 0); /** * Comparing the key/value extracted by {@code keyExtractor} by {@code nullsLast()} comparator. * * @param * @param keyExtractor * @return * @throws IllegalArgumentException * @see #comparingByIfNotNullOrElseNullsFirst(Function) * @see #comparingByIfNotNullOrElseNullsLast(Function) */ public static Comparator nullsLastBy(@SuppressWarnings("rawtypes") final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> NULL_LAST_COMPARATOR.compare(keyExtractor.apply(a), keyExtractor.apply(b)); } /** * * @param * @return */ @Beta public static Comparator nullsLastOrElseEqual() { return NULLS_LAST_OR_ELSE_EQUAL; } /** * * @param * @return * @throws IllegalArgumentException */ public static > Comparator> emptiesFirst() throws IllegalArgumentException { return emptiesFirst(naturalOrder()); } /** * * @param * @param cmp * @return * @throws IllegalArgumentException */ public static Comparator> emptiesFirst(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); // return Comparators., T> comparingBy(o -> o.orElse(null), Comparator.nullsFirst(cmp)); return (a, b) -> a == null || a.isEmpty() ? (b == null || b.isEmpty() ? 0 : -1) : (b == null || b.isEmpty() ? 1 : cmp.compare(a.get(), b.get())); } /** * * @param * @return * @throws IllegalArgumentException */ public static > Comparator> emptiesLast() throws IllegalArgumentException { return emptiesLast(naturalOrder()); } /** * * @param * @param cmp * @return * @throws IllegalArgumentException */ public static Comparator> emptiesLast(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); // return Comparators., T> comparingBy(o -> o.orElse(null), Comparator.nullsLast(cmp)); return (a, b) -> a == null || a.isEmpty() ? (b == null || b.isEmpty() ? 0 : 1) : (b == null || b.isEmpty() ? -1 : cmp.compare(a.get(), b.get())); } /** * Comparing the key/value extracted by {@code keyExtractor} by {@code nullsFirst()} comparator. * * @param * @param keyExtractor * @return * @throws IllegalArgumentException * @see #nullsFirstBy(Function) * @see #nullsLastBy(Function) * @see #comparingByIfNotNullOrElseNullsFirst(Function) * @see #comparingByIfNotNullOrElseNullsLast(Function) */ public static Comparator comparingBy(@SuppressWarnings("rawtypes") final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> NATURAL_ORDER.compare(keyExtractor.apply(a), keyExtractor.apply(b)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ @Beta public static Comparator comparingByIfNotNullOrElseNullsFirst( @SuppressWarnings("rawtypes") final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); @SuppressWarnings("rawtypes") final Comparator cmp = NULL_FIRST_COMPARATOR; return (a, b) -> a == null ? (b == null ? 0 : -1) : (b == null ? 1 : cmp.compare(keyExtractor.apply(a), keyExtractor.apply(b))); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ @Beta public static Comparator comparingByIfNotNullOrElseNullsLast(@SuppressWarnings("rawtypes") final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); @SuppressWarnings("rawtypes") final Comparator cmp = NULL_LAST_COMPARATOR; return (a, b) -> a == null ? (b == null ? 0 : 1) : (b == null ? -1 : cmp.compare(keyExtractor.apply(a), keyExtractor.apply(b))); } /** * * @param * @param * @param keyExtractor * @param keyComparator * @return * @throws IllegalArgumentException * @see #comparingByIfNotNullOrElseNullsFirst(Function, Comparator) * @see #comparingByIfNotNullOrElseNullsLast(Function, Comparator) */ public static Comparator comparingBy(final Function keyExtractor, final Comparator keyComparator) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); N.checkArgNotNull(keyComparator); return (a, b) -> keyComparator.compare(keyExtractor.apply(a), keyExtractor.apply(b)); } /** * * @param * @param * @param keyExtractor * @param keyComparator * @return * @throws IllegalArgumentException */ public static Comparator comparingByIfNotNullOrElseNullsFirst(final Function keyExtractor, final Comparator keyComparator) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); N.checkArgNotNull(keyComparator); return (a, b) -> a == null ? (b == null ? 0 : -1) : (b == null ? 1 : keyComparator.compare(keyExtractor.apply(a), keyExtractor.apply(b))); } /** * * @param * @param * @param keyExtractor * @param keyComparator * @return * @throws IllegalArgumentException */ public static Comparator comparingByIfNotNullOrElseNullsLast(final Function keyExtractor, final Comparator keyComparator) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); N.checkArgNotNull(keyComparator); return (a, b) -> a == null ? (b == null ? 0 : 1) : (b == null ? -1 : keyComparator.compare(keyExtractor.apply(a), keyExtractor.apply(b))); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingBoolean(final ToBooleanFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Boolean.compare(keyExtractor.applyAsBoolean(a), keyExtractor.applyAsBoolean(b)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingChar(final ToCharFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return Comparator.comparingInt(keyExtractor::applyAsChar); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingByte(final ToByteFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return Comparator.comparingInt(keyExtractor::applyAsByte); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingShort(final ToShortFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return Comparator.comparingInt(keyExtractor::applyAsShort); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingInt(final ToIntFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return Comparator.comparingInt(keyExtractor); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingLong(final ToLongFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return Comparator.comparingLong(keyExtractor); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingFloat(final ToFloatFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Float.compare(keyExtractor.applyAsFloat(a), keyExtractor.applyAsFloat(b)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingDouble(final ToDoubleFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return Comparator.comparingDouble(keyExtractor); } /** * Comparing ignore case. * * @return */ public static Comparator comparingIgnoreCase() { return COMPARING_IGNORE_CASE; } /** * Comparing ignore case. * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator comparingIgnoreCase(final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> COMPARING_IGNORE_CASE.compare(keyExtractor.apply(a), keyExtractor.apply(b)); } /** * Comparing by key. * * @param the key type * @param the value type * @return */ public static , V> Comparator> comparingByKey() { return (a, b) -> NATURAL_ORDER.compare(a.getKey(), b.getKey()); } /** * Comparing by value. * * @param the key type * @param the value type * @return */ public static > Comparator> comparingByValue() { return (a, b) -> NATURAL_ORDER.compare(a.getValue(), b.getValue()); } /** * Comparing by key. * * @param the key type * @param the value type * @param cmp * @return * @throws IllegalArgumentException */ public static Comparator> comparingByKey(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); return (a, b) -> cmp.compare(a.getKey(), b.getKey()); } /** * Comparing by value. * * @param the key type * @param the value type * @param cmp * @return * @throws IllegalArgumentException */ public static Comparator> comparingByValue(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); return (a, b) -> cmp.compare(a.getValue(), b.getValue()); } /** * Comparing by length. * * @param * @return */ public static Comparator comparingByLength() { return (Comparator) COMPARING_BY_LENGTH; } /** * Comparing by array length. * * @param * @return */ public static Comparator comparingByArrayLength() { return (Comparator) COMPARING_BY_ARRAY_LENGTH; } /** * Comparing by collection size. * * @param * @return */ @SuppressWarnings("rawtypes") public static Comparator comparingBySize() { return (Comparator) COMPARING_BY_SIZE; } /** * Comparing by map size. * * @param * @return */ @SuppressWarnings("rawtypes") public static Comparator comparingByMapSize() { return (Comparator) COMPARING_BY_MAP_SIZE; } // /** // * // * // * @return // */ // public static Comparator comparingObjArray() { // return comparingObjArray(naturalOrder()); // } /** * * @param cmp * @return */ @SuppressWarnings("rawtypes") public static Comparator comparingObjArray(final Comparator cmp) { return comparingArray((Comparator) cmp); } /** * * @param * @return */ @SuppressWarnings("rawtypes") public static Comparator comparingArray() { return comparingArray(NATURAL_ORDER); } /** * * @param * @param cmp * @return * @throws IllegalArgumentException */ public static Comparator comparingArray(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); return (a, b) -> { if (N.isEmpty(a)) { return N.isEmpty(b) ? 0 : -1; } else if (N.isEmpty(b)) { return 1; } final int lenA = N.len(a); final int lenB = N.len(b); int result = 0; for (int i = 0, minLen = N.min(lenA, lenB); i < minLen; i++) { result = cmp.compare(a[i], b[i]); if (result != 0) { return result; } } return Integer.compare(lenA, lenB); }; } /** * * @param * @return */ @SuppressWarnings("rawtypes") public static > Comparator comparingCollection() { return comparingCollection(NATURAL_ORDER); } /** * * @param * @param * @param cmp * @return * @throws IllegalArgumentException */ public static > Comparator comparingCollection(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); return (a, b) -> { if (N.isEmpty(a)) { return N.isEmpty(b) ? 0 : -1; } else if (N.isEmpty(b)) { return 1; } final Iterator iterA = a.iterator(); final Iterator iterB = b.iterator(); final int sizeA = N.size(a); final int sizeB = N.size(b); int result = 0; for (int i = 0, minLen = N.min(sizeA, sizeB); i < minLen; i++) { result = cmp.compare(iterA.next(), iterB.next()); if (result != 0) { return result; } } return Integer.compare(sizeA, sizeB); }; } /** * * @param * @return */ @SuppressWarnings("rawtypes") public static > Comparator comparingIterable() { return comparingIterable(NATURAL_ORDER); } /** * * @param * @param * @param cmp * @return * @throws IllegalArgumentException */ public static > Comparator comparingIterable(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); return (a, b) -> { final Iterator iterA = N.iterate(a); final Iterator iterB = N.iterate(b); if (N.isEmpty(iterA)) { return N.isEmpty(iterB) ? 0 : -1; } else if (N.isEmpty(iterB)) { return 1; } int result = 0; while (iterA.hasNext() && iterB.hasNext()) { result = cmp.compare(iterA.next(), iterB.next()); if (result != 0) { return result; } } return iterA.hasNext() ? 1 : (iterB.hasNext() ? -1 : 0); }; } /** * * @param * @return */ @SuppressWarnings("rawtypes") public static > Comparator comparingIterator() { return comparingIterator(NATURAL_ORDER); } /** * * @param * @param * @param cmp * @return * @throws IllegalArgumentException */ public static > Comparator comparingIterator(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); return (a, b) -> { if (N.isEmpty(a)) { return N.isEmpty(b) ? 0 : -1; } else if (N.isEmpty(b)) { return 1; } int result = 0; while (a.hasNext() && b.hasNext()) { result = cmp.compare(a.next(), b.next()); if (result != 0) { return result; } } return a.hasNext() ? 1 : (b.hasNext() ? -1 : 0); }; } /** * * @param * @return */ @SuppressWarnings("rawtypes") public static > Comparator comparingMapByKey() { return comparingMapByKey(NATURAL_ORDER); } /** * * @param * @param * @param cmp * @return * @throws IllegalArgumentException */ public static > Comparator comparingMapByKey(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); return (a, b) -> { if (N.isEmpty(a)) { return N.isEmpty(b) ? 0 : -1; } else if (N.isEmpty(b)) { return 1; } final Iterator iterA = a.keySet().iterator(); final Iterator iterB = b.keySet().iterator(); final int sizeA = N.size(a); final int sizeB = N.size(b); int result = 0; for (int i = 0, minLen = N.min(sizeA, sizeB); i < minLen; i++) { result = cmp.compare(iterA.next(), iterB.next()); if (result != 0) { return result; } } return Integer.compare(sizeA, sizeB); }; } /** * * @param * @return */ @SuppressWarnings("rawtypes") public static > Comparator comparingMapByValue() { return comparingMapByValue(NATURAL_ORDER); } /** * * @param * @param * @param cmp * @return * @throws IllegalArgumentException */ public static > Comparator comparingMapByValue(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); return (a, b) -> { if (N.isEmpty(a)) { return N.isEmpty(b) ? 0 : -1; } else if (N.isEmpty(b)) { return 1; } final Iterator iterA = a.values().iterator(); final Iterator iterB = b.values().iterator(); final int sizeA = N.size(a); final int sizeB = N.size(b); int result = 0; for (int i = 0, minLen = N.min(sizeA, sizeB); i < minLen; i++) { result = cmp.compare(iterA.next(), iterB.next()); if (result != 0) { return result; } } return Integer.compare(sizeA, sizeB); }; } /** * * @param * @param propNamesToCompare * @return * @throws IllegalArgumentException * @deprecated call {@code getPropValue} by reflection apis during comparing or sorting may have huge impact to performance. Use {@link ComparisonBuilder} instead. * @see Builder#compare(Object, Object, Comparator) * @see {@link ComparisonBuilder} */ @Deprecated public static Comparator comparingBeanByProps(final Collection propNamesToCompare) throws IllegalArgumentException { return (a, b) -> N.compareByProps(a, b, propNamesToCompare); } /** * * @param * @return */ @SuppressWarnings("rawtypes") public static Comparator reverseOrder() { return REVERSED_ORDER; } /** * * @param * @param cmp * @return */ public static Comparator reverseOrder(final Comparator cmp) { if (cmp == null || cmp == NATURAL_ORDER) { // NOSONAR return REVERSED_ORDER; } else if (cmp == REVERSED_ORDER) { // NOSONAR return NATURAL_ORDER; } return Collections.reverseOrder(cmp); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator reversedComparingBoolean(final ToBooleanFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Boolean.compare(keyExtractor.applyAsBoolean(b), keyExtractor.applyAsBoolean(a)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator reversedComparingChar(final ToCharFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Character.compare(keyExtractor.applyAsChar(b), keyExtractor.applyAsChar(a)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator reversedComparingByte(final ToByteFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Byte.compare(keyExtractor.applyAsByte(b), keyExtractor.applyAsByte(a)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator reversedComparingShort(final ToShortFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Short.compare(keyExtractor.applyAsShort(b), keyExtractor.applyAsShort(a)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator reversedComparingInt(final ToIntFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Integer.compare(keyExtractor.applyAsInt(b), keyExtractor.applyAsInt(a)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator reversedComparingLong(final ToLongFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Long.compare(keyExtractor.applyAsLong(b), keyExtractor.applyAsLong(a)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator reversedComparingFloat(final ToFloatFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Float.compare(keyExtractor.applyAsFloat(b), keyExtractor.applyAsFloat(a)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ public static Comparator reversedComparingDouble(final ToDoubleFunction keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> Double.compare(keyExtractor.applyAsDouble(b), keyExtractor.applyAsDouble(a)); } /** * Reversed comparing by. * * @param * @param keyExtractor * @return * @throws IllegalArgumentException * @see #reversedComparingByIfNotNullOrElseNullsFirst(Function) * @see #reversedComparingByIfNotNullOrElseNullsLast(Function) */ public static Comparator reversedComparingBy(@SuppressWarnings("rawtypes") final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); return (a, b) -> REVERSED_ORDER.compare(keyExtractor.apply(a), keyExtractor.apply(b)); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ @Beta public static Comparator reversedComparingByIfNotNullOrElseNullsFirst( @SuppressWarnings("rawtypes") final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); @SuppressWarnings("rawtypes") final Comparator cmp = NULL_FIRST_REVERSED_ORDER; return (a, b) -> a == null ? (b == null ? 0 : -1) : (b == null ? 1 : cmp.compare(keyExtractor.apply(a), keyExtractor.apply(b))); } /** * * @param * @param keyExtractor * @return * @throws IllegalArgumentException */ @Beta public static Comparator reversedComparingByIfNotNullOrElseNullsLast( @SuppressWarnings("rawtypes") final Function keyExtractor) throws IllegalArgumentException { N.checkArgNotNull(keyExtractor); @SuppressWarnings("rawtypes") final Comparator cmp = NULL_LAST_REVERSED_ORDER; return (a, b) -> a == null ? (b == null ? 0 : 1) : (b == null ? -1 : cmp.compare(keyExtractor.apply(a), keyExtractor.apply(b))); } /** * Reversed comparing by key. * * @param the key type * @param the value type * @return */ public static , V> Comparator> reversedComparingByKey() { return (a, b) -> REVERSED_ORDER.compare(a.getKey(), b.getKey()); } /** * Reversed comparing by value. * * @param the key type * @param the value type * @return */ public static > Comparator> reversedComparingByValue() { return (a, b) -> REVERSED_ORDER.compare(a.getValue(), b.getValue()); } /** * Reversed comparing by key. * * @param the key type * @param the value type * @param cmp * @return * @throws IllegalArgumentException */ @Beta public static Comparator> reversedComparingByKey(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); final Comparator reversedOrder = reverseOrder(cmp); return (a, b) -> reversedOrder.compare(a.getKey(), b.getKey()); } /** * Reversed comparing by value. * * @param the key type * @param the value type * @param cmp * @return * @throws IllegalArgumentException */ @Beta public static Comparator> reversedComparingByValue(final Comparator cmp) throws IllegalArgumentException { N.checkArgNotNull(cmp); final Comparator reversedOrder = reverseOrder(cmp); return (a, b) -> reversedOrder.compare(a.getValue(), b.getValue()); } }