I want to sort a list with Lambda:
List messagesByDeviceType = new ArrayList();
messagesByDeviceType.sort((Message o1, Messag
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 -> LambdaBodyAny 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:
Comparator#compareTo returns an int; while getTime is obviously long.
It would be nicer written like this:
.sort(Comparator.comparingLong(Message::getTime))
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.
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.
In the place of Developer write your class name
Comparator<Developer> byName =
(Developer o1, Developer o2)->o1.getName().compareTo(o2.getName());
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.
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())
- in Comparator, which may causes overflow, in some cases, and crash your program.