Java 8 Lambda: Comparateur
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)
-> {})
5 réponses
Comparator#compareTo
retourne un int
; tandis que getTime
est évidemment long
.
Ce serait mieux écrit comme ceci:
.sort(Comparator.comparingLong(Message::getTime))
le Comparator
's compare()
méthode doit retourner un int
, et il semble que le vôtre retourne un long
.
vous pouvez le changer en:
(Message o1, Message o2)->Long.compare(o1.getTime(),o2.getTime())
ceci suppose (basé sur votre message d'erreur) que o1.getTime()
retourne un long
.
Lambda
La lambda peut être vu comme l'abréviation d'un peu lourd classe anonyme:
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();
}
});
ainsi, chaque fois que vous êtes confus comment écrire une lambda droite, vous pouvez essayer d'écrire une version pré-lambda, et voir comment il est faux.
Application
dans votre problème , vous pouvez voir le compare
retourne int
, où votre getTime
retourne long, qui est la source d'erreur.
vous pouvez utiliser l'une ou l'autre méthode comme autre méthode de réponse, comme:
Long.compare(o1.getTime(),o2.getTime())
Avis
- vous devez éviter d'utiliser
-
dansComparator
, ce qui peut causer un débordement, dans certains cas, et planter votre programme.
comparateur
nous utilisons l'interface de comparateur pour trier les éléments homogènes et hétérogènes pour l'ordre de tri personnalisé 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 en versions antérieures de Java 8 utilisant les Classes internes.
une classe anonyme ne peut pas accéder aux variables locales dans son champ d'application qui ne sont pas déclarées comme finales ou effectivement 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 des paramètres formels et un corps - une expression ou un bloc - exprimé en termes de ces paramètres.
LambdaExpression :
LambdaParameters -> LambdaBody
toute variable locale, tout paramètre formel ou tout paramètre d'exception utilisé mais non déclaré dans une expression lambda doit être déclaré final ou effectivement final, ou une erreur de compilation se produit lorsque l'utilisation est tenter.
Comparator<Employee> functional_semantics = (e1, e2) -> {
return e1.getCreationTime().compareTo( e2.getCreationTime() );
};
Basique avec le Soutien de Lambda
Comparator<Employee> timeCompareLambda = (o1, o2) -> (int) ( o1.getCreationTime() - o2.getCreationTime());
Collections.sort(java8, timeCompareLambda );
utilisant clé D'extraction et méthode de comparaison : un comparateur qui compare par une touche 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 );
Essai Sur Échantillon 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
}
voir ces posts également:
Vous devriez changer
messagesByDeviceType.sort( (Message o1, Message o2) -> o1.getTime() - o2.getTime() );
à
messagesByDeviceType.sort(
Comparator.comparing((Message m) -> m.getTime())
);
qui suppose que la valeur est Comparable
, ce qui fournit un ordre de tri naturel.
si vous voulez ajouter plus de champs, vous pouvez les enchaîner au comparateur. par exemple, pour trier d'abord par le temps, et puis par l'expéditeur:
messagesByDeviceType.sort(
Comparator
.comparing((Message m) -> m.getTime())
.thenComparing((m) -> m.getSender())
);
pour inverser l'ordre de tout Comparator
, enchaîner le reveresed()
méthode pour cela, p.ex. pour trier d'abord par décroissance temporelle, 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