美文网首页
一个Java8比较器

一个Java8比较器

作者: mingdongz | 来源:发表于2018-02-04 12:09 被阅读0次

    最近在开发中,重构背包功能时,需要对物品进行多级排序。

    用传统的Java语法很难实现,所以写了个函数式比较器,特点有

    1. 支持链式分级排序
    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;
    
    /**
     * 增强排序器,支持逆向排序和条件移动
     * 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);
        }
    
    }
    

    函数式范式表达力真的强!!

    ( PS: 现在没学个Scala/Clojure好意思说自己会java ;) !! )

    相关文章

      网友评论

          本文标题:一个Java8比较器

          本文链接:https://www.haomeiwen.com/subject/fprmzxtx.html