sort - order list stream java 8
Java 8 Lambda: comparador (5)
Quiero ordenar una lista con Lambda:
List<Message> messagesByDeviceType = new ArrayList<Message>();
messagesByDeviceType.sort((Message o1, Message o2)->o1.getTime()-o2.getTime());
Pero tengo este error de compilación:
Multiple markers at this line
- Type mismatch: cannot convert from long to int
- The method sort(Comparator<? super Message>) in the type List<Message> is not applicable for the arguments ((Message o1, Message o2)
-> {})
Lambda
La lambda puede verse como la abreviatura de una clase anónima algo engorrosa:
La versión de Java8:
Collections.sort(list, (o1, o2) -> o1.getTime() - o2.getTime());
Versión previa a Java8:
Collections.sort(list, new Comparator<Message>() {
@Override
public int compare(Message o1, Message o2) {
return o1.getTime() - o2.getTime();
}
});
Entonces, cada vez que te confundas sobre cómo escribir un lambda correcto, puedes intentar escribir una versión pre lambda y ver cómo está mal.
Solicitud
En su problema específico, puede ver los retornos de compare
int
, donde getTime
devuelve long, que es la fuente de error.
Puede usar cualquiera de los métodos como otro método de respuesta, como:
Long.compare(o1.getTime(),o2.getTime())
darse cuenta
- Debe evitar usar
-
en elComparator
, que puede causar desbordamiento, en algunos casos, y bloquear su programa.
Debes cambiar
messagesByDeviceType.sort((Message o1, Message o2)->o1.getTime()-o2.getTime());
a
messagesByDeviceType.sort(
Comparator.comparing((Message m) -> m.getTime())
);
Eso supone que el valor es Comparable
, lo que proporciona un orden de clasificación natural.
Si desea agregar más campos, puede encadenarlos al Comparador. por ejemplo, ordenar primero por tiempo y luego por remitente:
messagesByDeviceType.sort(
Comparator
.comparing((Message m) -> m.getTime())
.thenComparing((m) -> m.getSender())
);
Para invertir el orden de cualquier Comparator
, encadena el método reveresed()
, por ejemplo, para ordenar primero por tiempo descendiendo, y luego por el remitente:
messagesByDeviceType.sort(
Comparator
.comparing((Message m) -> m.getTime())
.reversed()
.thenComparing((m) -> m.getSender())
);
Ver también https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html
El método compare()
Comparator
debe devolver un int
, y parece que el suyo está retornando un long
.
Puedes cambiarlo a:
(Message o1, Message o2)->Long.compare(o1.getTime(),o2.getTime())
Esto supone (basado en su mensaje de error) que o1.getTime()
devuelve un valor long
.
Comparator#compareTo
devuelve un int
; mientras que getTime
es obviamente long
.
Sería mejor escrito así:
.sort(Comparator.comparingLong(Message::getTime))
Comparador
Utilizamos la interfaz del comparador para ordenar elementos homogéneos y heterogéneos para el orden de clasificación predeterminado y personalizado.
int compare(T o1, T o2);
toma dos argumentos para ordenar. Devuelve un
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.
Anónimo Clasifica cómo ordenar una lista de objetos en versiones anteriores de Java 8 utilizando clases internas.
Una clase anónima no puede acceder a las variables locales en su ámbito adjunto que no están declaradas como finales o efectivamente finales.
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
Una expresión lambda es como un método: proporciona una lista de parámetros formales y un cuerpo, una expresión o bloque, expresado en términos de esos parámetros.
LambdaExpression :
LambdaParameters -> LambdaBody
Cualquier variable local, parámetro formal o parámetro de excepción utilizado pero no declarado en una expresión lambda debe declararse final o efectivamente final, o se produce un error en tiempo de compilación cuando se intenta utilizar.
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 );
Uso de la clave extraída y el método de comparación : un comparador que se compara con una clave extraída. Pasar referencias usando :: palabra clave.
static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
ToLongFunction<Employee> keyExtracor = Employee::getCreationTime;
Comparator<Employee> byTime = Comparator.comparingLong( Employee::getCreationTime );
Código de prueba de muestra:
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
}
Ver estas publicaciones también:
- Tutorial de Java 8
- Java8 Lambdas vs clases anónimas
- Lambda vs rendimiento anónimo de clase interna