sort java lambda java-8 comparator

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 el Comparator , 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