一個Java8比較器

最近在開發(fā)中,重構(gòu)背包功能時,需要對物品進(jìn)行多級排序。

用傳統(tǒng)的Java語法很難實現(xiàn),所以寫了個函數(shù)式比較器,特點(diǎn)有

  1. 支持鏈?zhǔn)椒旨壟判?/li>
  2. 支持正序、逆序排
  3. 支持按條件移動(前移后移)

下面給個簡單例子

public static void main(String[] args) {
    List<Employee> employeeList = Arrays.asList(
    Employee.builder().id(101).name("Matt").gender("male").salary(5000).office("New York").build(),
    Employee.builder().id(102).name("Sheila").gender("female").salary(6000).office("London").build(),
    Employee.builder().id(103).name("Carrie").gender("male").salary(20000).office("New York").build(),
    Employee.builder().id(104).name("Hannah").gender("female").salary(7000).office("New York").build(),
    Employee.builder().id(105).name("Pat").gender("male").salary(8000).office("London").build(),
    Employee.builder().id(106).name("Elin").gender("female").salary(29000).office("Shanghai").build()
    
    );

    Collections.sort(employeeList, 
            //男性移動到下面
        ComparatorPlus.<Employee>moveBack( x -> "male".equals(x.getGender()))
            //"New York"的往前排
            .thenMoveForward(x -> "New York".equals(x.getOffice()))
            //再按 薪水倒排
            .thenReversedComparing(Employee::getSalary)
    );

    System.out.println("----");
    employeeList.forEach(System.out::println);
}

output:
Employee(id=104, name=Hannah, gender=female, salary=7000, office=New York)
Employee(id=106, name=Elin, gender=female, salary=29000, office=Shanghai)
Employee(id=102, name=Sheila, gender=female, salary=6000, office=London)
Employee(id=103, name=Carrie, gender=male, salary=20000, office=New York)
Employee(id=101, name=Matt, gender=male, salary=5000, office=New York)
Employee(id=105, name=Pat, gender=male, salary=8000, office=London)

最后,附上比較器源碼


import java.io.Serializable;
import java.util.Comparator;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * 增強(qiáng)排序器,支持逆向排序和條件移動
 * Created by adam.zh on 2018/1/20
 */
@FunctionalInterface
public interface ComparatorPlus<T> extends Comparator<T> {
    @Override
    int compare(T o1, T o2);

    public static <T, U extends Comparable<? super U>> ComparatorPlus<T> comparing(
            Function<? super T, ? extends U> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (ComparatorPlus<T> & Serializable)
                (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

    public static <T, U extends Comparable<? super U>> ComparatorPlus<T> reversedComparing(
            Function<? super T, ? extends U> keyExtractor) {
        return (ComparatorPlus<T> & Serializable) comparing(keyExtractor).reversed();
    }


    public static <T> ComparatorPlus<T> moveForward(
            Predicate<? super T> predicate) {
        return moveBack(predicate.negate());
    }

    public static <T> ComparatorPlus<T> moveForward(
            Predicate<? super T> predicate,
            Comparator<? super T> sub) {
        return (ComparatorPlus<T> & Serializable) (c1, c2) ->
                predicate.test(c1) && predicate.test(c2) ? sub.compare(c1, c2)
                        : moveForward(predicate).compare(c1, c2);
    }

    public static <T> ComparatorPlus<T> moveForward(
            Predicate<? super T> predicate,
            Comparator<? super T> sub1,
            Comparator<? super T> sub2
    ) {
        return (ComparatorPlus<T> & Serializable) (c1, c2) ->
                !predicate.test(c1) && !predicate.test(c2) ? sub2.compare(c1, c2)
                        : moveForward(predicate, sub1).compare(c1, c2);
    }

    public static <T> ComparatorPlus<T> moveBack(
            Predicate<? super T> predicate) {
        return (ComparatorPlus<T> & Serializable) (c1, c2) ->
                Boolean.compare(predicate.test(c1), predicate.test(c2));
    }

    public static <T> ComparatorPlus<T> moveBack(
            Predicate<? super T> predicate,
            Comparator<? super T> sub) {
        return (ComparatorPlus<T> & Serializable) (c1, c2) ->
                predicate.test(c1) && predicate.test(c2) ? sub.compare(c1, c2)
                        : moveBack(predicate).compare(c1, c2);
    }

    public static <T> ComparatorPlus<T> moveBack(
            Predicate<? super T> predicate,
            Comparator<? super T> sub1,
            Comparator<? super T> sub2) {
        return (ComparatorPlus<T> & Serializable) (c1, c2) ->
                !predicate.test(c1) && !predicate.test(c2) ? sub2.compare(c1, c2)
                        : moveBack(predicate, sub1).compare(c1, c2);
    }

    default ComparatorPlus<T> thenComparing(Comparator<? super T> other) {
        Objects.requireNonNull(other);
        return (ComparatorPlus<T> & Serializable) (c1, c2) -> {
            int res = compare(c1, c2);
            return (res != 0) ? res : other.compare(c1, c2);
        };
    }

    default <U extends Comparable<? super U>> ComparatorPlus<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor) {
        return thenComparing(comparing(keyExtractor));
    }

    default ComparatorPlus<T> thenReversedComparing(Comparator<? super T> other) {
        return thenComparing(other.reversed());
    }

    default <U extends Comparable<? super U>> ComparatorPlus<T> thenReversedComparing(
            Function<? super T, ? extends U> keyExtractor) {
        return thenReversedComparing(comparing(keyExtractor));
    }


    default ComparatorPlus<T> thenMoveForward(Predicate<? super T> predicate) {
        return thenComparing(moveForward(predicate));
    }

    default ComparatorPlus<T> thenMoveForward(
            Predicate<? super T> predicate,
            Comparator<? super T> sub) {
        return thenComparing(moveForward(predicate, sub));
    }

    default ComparatorPlus<T> thenMoveForward(
            Predicate<? super T> predicate,
            Comparator<? super T> sub1,
            Comparator<? super T> sub2) {
        return thenComparing(moveForward(predicate, sub1, sub2));
    }

    default ComparatorPlus<T> thenMoveBack(Predicate<? super T> predicate) {
        return thenComparing(moveBack(predicate));
    }

    default ComparatorPlus<T> thenMoveBack(
            Predicate<? super T> predicate,
            Comparator<? super T> sub) {
        return thenComparing(moveBack(predicate, sub));
    }

    default ComparatorPlus<T> thenMoveBack(
            Predicate<? super T> predicate,
            Comparator<? super T> sub1,
            Comparator<? super T> sub2) {
        return thenComparing(moveBack(predicate, sub1, sub2));
    }


    // flip!!
    default ComparatorPlus<T> reversed() {
        return (ComparatorPlus<T> & Serializable) (c1, c2) -> this.compare(c2, c1);
    }

}

函數(shù)式范式表達(dá)力真的強(qiáng)??!

( PS: 現(xiàn)在沒學(xué)個Scala/Clojure好意思說自己會java ;) !! )

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容