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 ())
Хорошо объяснено относительно лямбда-компаратора в представленной ниже ссылке на видео.
ламда-компаратор
In the place of Developer write your class name
Comparator<Developer> byName =
(Developer o1, Developer o2)->o1.getName().compareTo(o2.getName());