Java 8 Lambda: Comparator

前端 未结 7 1445
鱼传尺愫
鱼传尺愫 2021-02-01 12:53

I want to sort a list with Lambda:

List messagesByDeviceType = new ArrayList();      
messagesByDeviceType.sort((Message o1, Messag         


        
相关标签:
7条回答
  • 2021-02-01 13:22

    Comparator

    We use comparator interface to sort homogeneous and heterogeneous elements for default, customized sorting order.

    int compare(T o1, T o2);
    

    it takes two arguments for ordering. Returns a

        negative integer(-1) « if first argument is less than the other
        zero             (0) « if both are equal
        positive integer (1) « if first greater than the second.
    

    Anonymous Classes how to sort a list of objects in prior versions of Java 8 using inner Classes.

    An anonymous class cannot access local variables in its enclosing scope that are not declared as final or effectively final.

    Comparator<Employee> timeCompare = new Comparator<Employee>() {
        @Override public int compare(Employee e1, Employee e2) {
            return e1.getCreationTime().compareTo( e2.getCreationTime() );
        }
    };
    

    Java 8 Lambda Expressions uing compare method

    A lambda expression is like a method: it provides a list of formal parameters and a body - an expression or block - expressed in terms of those parameters.

    LambdaExpression: LambdaParameters -> LambdaBody

    Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final, or a compile-time error occurs where the use is attempted.

    Comparator<Employee> functional_semantics = (e1, e2) -> {
       return e1.getCreationTime().compareTo( e2.getCreationTime() );
    };
    

    Basic Sort with Lambda Support

    Comparator<Employee> timeCompareLambda = (o1, o2) -> (int) ( o1.getCreationTime() - o2.getCreationTime());
    Collections.sort(java8, timeCompareLambda );
    

    Using Extracted Key and Comparing method: A comparator that compares by an extracted key. Pass references using :: keyword.

    static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
    
    ToLongFunction<Employee> keyExtracor = Employee::getCreationTime;
    Comparator<Employee> byTime = Comparator.comparingLong( Employee::getCreationTime );
    

    Sample Test Code:

    public class Lambda_Long_Comparator {
        public static void main(String[] args) {
    
            List<Employee> java7 = getEmployees();
    
            // Sort with Inner Class
            Comparator<Employee> timeCompare = new Comparator<Employee>() {
                @Override public int compare(Employee e1, Employee e2) {
                    return e1.getCreationTime().compareTo( e2.getCreationTime() );
                }
            };
    
            // Collections.sort(list); // Defaults to Comparable<T> « @compareTo(o1)
            Collections.sort(java7, timeCompare); // Comparator<T> « @compare (o1,o2)
            System.out.println("Java < 8 \n"+ java7);
    
            List<Employee> java8 = getEmployees();
            Collections.sort(java8, Comparator
                    .comparing( Employee::getCreationTime )
                    .thenComparing( Employee::getName ));
            //java8.forEach((emp)-> System.out.println(emp));
            System.out.println("Java 8 \n"+java8);
        }
    
        static List<Employee> getEmployees() {
            Date date = Calendar.getInstance().getTime();
            List<Employee> list = new ArrayList<Employee>();
            list.add( new Employee(4, "Yash", date.getTime()+7));
            list.add( new Employee(2, "Raju", date.getTime()+1));
            list.add( new Employee(4, "Yas", date.getTime()));
            list.add( new Employee(7, "Sam", date.getTime()-4));
            list.add( new Employee(8, "John", date.getTime()));
            return list;
        }
    }
    class Employee implements Comparable<Employee> {
        Integer id;
        String name;
        Long creationTime;
    
        public Employee(Integer id, String name, Long creationTime) {
            this.id = id;
            this.name = name;
            this.creationTime = creationTime;
        }
    
        @Override public int compareTo(Employee e) {
            return this.id.compareTo(e.id);
        }
    
        @Override public String toString() {
            return "\n["+this.id+","+this.name+","+this.creationTime+"]";
        }
    
        // Other getter and setter methods
    }
    

    See these posts also:

    • Java 8 Tutorial
    • Java8 Lambdas vs Anonymous classes
    • Lambda vs anonymous inner class performance
    0 讨论(0)
  • 2021-02-01 13:24

    Comparator#compareTo returns an int; while getTime is obviously long.

    It would be nicer written like this:

     .sort(Comparator.comparingLong(Message::getTime))
    
    0 讨论(0)
  • 2021-02-01 13:24

    The compare() method must return an int, and it seems yours is returning a long.

    You can change it this into:

    Long.compare(o1.getTime(),o2.getTime())
    

    Well explained regarding lambda comparator in the below presented video link.

    0 讨论(0)
  • The Comparator's compare() method must return an int, and it seems yours is returning a long.

    You can change it to:

    (Message o1, Message o2)->Long.compare(o1.getTime(),o2.getTime())
    

    This is assuming (based on your error message) that o1.getTime() returns a long.

    0 讨论(0)
  • 2021-02-01 13:38

    lamda comparator

    In the place of Developer write your class name 
    
        Comparator<Developer> byName = 
            (Developer o1, Developer o2)->o1.getName().compareTo(o2.getName());
    
    0 讨论(0)
  • 2021-02-01 13:39

    Lambda

    The lambda can be seen as the shorthand of somewhat cumbersome anonymous class:

    Java8 version:

    Collections.sort(list, (o1, o2) -> o1.getTime() - o2.getTime());
    

    Pre-Java8 version:

        Collections.sort(list, new Comparator<Message>() {
            @Override
            public int compare(Message o1, Message o2) {
                return o1.getTime() - o2.getTime();
            }
        }); 
    

    So, every time you are confused how to write a right lambda, you may try to write a pre-lambda version, and see how it is wrong.

    Application

    In your specific problem, you can see the compare returns int, where your getTime returns long, which is the source of error.

    You may use either method as other answer method, like:

    Long.compare(o1.getTime(),o2.getTime())
    

    Notice

    • You should avoid using - in Comparator, which may causes overflow, in some cases, and crash your program.
    0 讨论(0)
提交回复
热议问题