Java 8 Lambda: компаратор

Я хочу отсортировать список с помощью Lambda:

List<Message> messagesByDeviceType = new ArrayList<Message>();      
messagesByDeviceType.sort((Message o1, Message o2)->o1.getTime()-o2.getTime());

Но я получил эту ошибку компиляции:

 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 ответов

Решение

Comparator#compareTo возвращает int; в то время как getTime очевидно long,

Было бы лучше написать так:

 .sort(Comparator.comparingLong(Message::getTime))

лямбда

Лямбда можно рассматривать как стенографию несколько громоздкого анонимного класса:

Версия Java8:

Collections.sort(list, (o1, o2) -> o1.getTime() - o2.getTime());

Версия до Java8:

    Collections.sort(list, new Comparator<Message>() {
        @Override
        public int compare(Message o1, Message o2) {
            return o1.getTime() - o2.getTime();
        }
    }); 

Таким образом, каждый раз, когда вы не понимаете, как написать правильную лямбду, вы можете попытаться написать предварительную лямбда-версию и посмотреть, как это неправильно.

заявка

В вашей конкретной проблеме вы можете увидеть compare возвращается int, где твой getTime возвращает long, что является источником ошибки.

Вы можете использовать любой метод как другой метод ответа, например:

Long.compare(o1.getTime(),o2.getTime())

уведомление

  • Вы должны избегать использования - в Comparator, что может вызвать переполнение, в некоторых случаях, и сбой вашей программы.

Comparator"s compare() метод должен вернуть intи, кажется, ваш возвращается long,

Вы можете изменить это на:

(Message o1, Message o2)->Long.compare(o1.getTime(),o2.getTime())

Это предполагает (на основе вашего сообщения об ошибке), что o1.getTime() возвращает long,

компаратор

Мы используем интерфейс компаратора для сортировки однородных и разнородных элементов по умолчанию, настраиваемый порядок сортировки.

int compare(T o1, T o2);

требуется два аргумента для заказа. Возвращает

    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.

Анонимные Классы, как сортировать список объектов в предыдущих версиях Java 8, используя внутренние Классы.

Анонимный класс не может получить доступ к локальным переменным в своей области видимости, которые не объявлены как окончательные или фактически окончательные.

Comparator<Employee> timeCompare = new Comparator<Employee>() {
    @Override public int compare(Employee e1, Employee e2) {
        return e1.getCreationTime().compareTo( e2.getCreationTime() );
    }
};

Java 8Lambda Expressionsметод сравнения

Лямбда-выражение похоже на метод: оно предоставляет список формальных параметров, а тело - выражение или блок - выражается в терминах этих параметров.

LambdaExpression: LambdaParameters -> LambdaBody

Любая локальная переменная, формальный параметр или параметр исключения, используемые, но не объявленные в лямбда-выражении, должны быть либо объявлены окончательными, либо фактически окончательными, либо при попытке использования возникает ошибка времени компиляции.

Comparator<Employee> functional_semantics = (e1, e2) -> {
   return e1.getCreationTime().compareTo( e2.getCreationTime() );
};

Базовая сортировка с поддержкой лямбды

Comparator<Employee> timeCompareLambda = (o1, o2) -> (int) ( o1.getCreationTime() - o2.getCreationTime());
Collections.sort(java8, timeCompareLambda );

Использованиеизвлеченного ключа и метода сравнения:компаратор, который сравнивает извлеченный ключ.Передайте ссылки, используя:: ключевое слово.

static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
ToLongFunction<Employee> keyExtracor = Employee::getCreationTime;
Comparator<Employee> byTime = Comparator.comparingLong( Employee::getCreationTime );

Образец тестового кода:

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
}

Смотрите эти посты также:

Вы должны изменить

 messagesByDeviceType.sort(
     (Message o1, Message o2) -> o1.getTime() - o2.getTime()
 );

в

messagesByDeviceType.sort(
    Comparator.comparing((Message m) -> m.getTime())
);

Это предполагает, что значение Comparable, что обеспечивает естественный порядок сортировки.

Если вы хотите добавить больше полей, вы можете связать их с компаратором. например, отсортировать сначала по времени, а затем по отправителю:

messagesByDeviceType.sort(
    Comparator
        .comparing((Message m) -> m.getTime())
        .thenComparing((m)     -> m.getSender())
);

В обратном порядке любой Comparator, цепочка reveresed() метод, например, сортировать сначала по убыванию времени, а затем по отправителю:

messagesByDeviceType.sort(
    Comparator
        .comparing((Message m) -> m.getTime())
        .reversed()
        .thenComparing((m)     -> m.getSender())
);

Смотрите также https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html

Метод compare () должен возвращать int, и, похоже, ваш возвращает long.

Вы можете изменить это на:

Long.compare (o1.getTime (), o2.getTime ())

Хорошо объяснено относительно лямбда-компаратора в представленной ниже ссылке на видео.

https://youtu.be/r7mYbTmWtUg

ламда-компаратор

In the place of Developer write your class name 

    Comparator<Developer> byName = 
        (Developer o1, Developer o2)->o1.getName().compareTo(o2.getName());
Другие вопросы по тегам