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) 
     -> {})
36
demandé sur Peter Mortensen 2017-05-28 12:44:27

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))
67
répondu Eugene 2017-05-28 09:47:58

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 .

18
répondu Eran 2017-05-28 09:46:39

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 - dans Comparator , ce qui peut causer un débordement, dans certains cas, et planter votre programme.
16
répondu Tony 2017-05-29 02:18:12

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:

6
répondu Yash 2017-09-06 12:23:46

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

3
répondu isapir 2018-10-02 17:14:44