Je veux trier une liste avec Lambda:
List<Message> messagesByDeviceType = new ArrayList<Message>();
messagesByDeviceType.sort((Message o1, Message o2)->o1.getTime()-o2.getTime());
Mais j'ai eu cette erreur de compilation:
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)
-> {})
Comparator#compareTo
retourne un int
; tandis que getTime
est évidemment long
.
Ce serait plus gentil d'écrire comme ça:
.sort(Comparator.comparingLong(Message::getTime))
La méthode Comparator
compare()
doit renvoyer un int
, et il semble que la vôtre renvoie un long
.
Vous pouvez le changer pour:
(Message o1, Message o2)->Long.compare(o1.getTime(),o2.getTime())
Ceci suppose (en fonction de votre message d'erreur) que o1.getTime()
renvoie un long
.
Le lambda peut être considéré comme le raccourci d'une classe anonyme quelque peu encombrante:
Version Java8:
Collections.sort(list, (o1, o2) -> o1.getTime() - o2.getTime());
Version antérieure à Java8:
Collections.sort(list, new Comparator<Message>() {
@Override
public int compare(Message o1, Message o2) {
return o1.getTime() - o2.getTime();
}
});
Ainsi, chaque fois que vous ne savez pas comment écrire un bon lambda, vous pouvez essayer d'écrire une version pré-lambda et voir en quoi c'est faux.
Dans votre problème spécifique, vous pouvez voir que compare
renvoie int
, où votre getTime
renvoie long, qui est la source de l'erreur.
Vous pouvez utiliser l'une ou l'autre méthode comme autre méthode de réponse, comme par exemple:
Long.compare(o1.getTime(),o2.getTime())
-
in Comparator
, ce qui peut provoquer un débordement dans certains cas et faire planter votre programme.Comparateur
Nous utilisons l’interface de comparateur pour trier les éléments homogènes et hétérogènes en vue d’un ordre de tri personnalisé et par défaut.
int compare(T o1, T o2);
il faut deux arguments pour commander. Retourne 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.
Classes anonymes comment trier une liste d'objets dans versions antérieures de Java 8 utilisant des classes internes.
Une classe anonyme ne peut pas accéder aux variables locales de sa portée englobante qui ne sont pas déclarées finales ou 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 méthode de comparaison
Une expression lambda est comme une méthode: elle fournit une liste de paramètres formels et un corps - une expression ou un bloc - exprimé en fonction de ces paramètres.
LambdaExpression :
LambdaParameters -> LambdaBody
Toute variable locale, paramètre formel ou paramètre d'exception utilisé mais non déclaré dans une expression lambda doit être soit déclaré final, soit être réellement final, sinon une erreur de compilation survient lors de la tentative d'utilisation.
Comparator<Employee> functional_semantics = (e1, e2) -> {
return e1.getCreationTime().compareTo( e2.getCreationTime() );
};
Tri de base avec support Lambda
Comparator<Employee> timeCompareLambda = (o1, o2) -> (int) ( o1.getCreationTime() - o2.getCreationTime());
Collections.sort(Java8, timeCompareLambda );
Utilisation de clé extraite et méthode de comparaison: Un comparateur comparant une clé extraite. Passer des références en utilisant :: mot-clé.
static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
ToLongFunction<Employee> keyExtracor = Employee::getCreationTime;
Comparator<Employee> byTime = Comparator.comparingLong( Employee::getCreationTime );
Exemple de code de test:
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
}
Voir ces articles aussi:
Tu devrais changer
messagesByDeviceType.sort( (Message o1, Message o2) -> o1.getTime() - o2.getTime() );
à
messagesByDeviceType.sort(
Comparator.comparing((Message m) -> m.getTime())
);
Cela suppose que la valeur est Comparable
, ce qui fournit un ordre de tri naturel.
Si vous souhaitez ajouter plus de champs, vous pouvez les chaîner au comparateur. par exemple. trier d'abord par heure, puis par expéditeur:
messagesByDeviceType.sort(
Comparator
.comparing((Message m) -> m.getTime())
.thenComparing((m) -> m.getSender())
);
Pour inverser l'ordre de toute méthode Comparator
, enchaînez la méthode reveresed()
, par ex. trier d'abord par heure décroissante, puis par expéditeur:
messagesByDeviceType.sort(
Comparator
.comparing((Message m) -> m.getTime())
.reversed()
.thenComparing((m) -> m.getSender())
);
Voir aussi https://docs.Oracle.com/javase/8/docs/api/Java/util/Comparator.html
La méthode compare()
doit renvoyer un int
, et il semble que le vôtre renvoie un long
.
Vous pouvez le changer en ceci:
Long.compare(o1.getTime(),o2.getTime())
Bien expliqué en ce qui concerne le comparateur lambda dans la vidéo présentée ci-dessous lien .