Java 8 Lambda:比较器
Java 8 Lambda: Comparator
我想用 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)
-> {})
Comparator
的 compare()
方法必须 return 一个 int
,你的似乎是 return 一个 long
。
您可以将其更改为:
(Message o1, Message o2)->Long.compare(o1.getTime(),o2.getTime())
这是假设(根据您的错误消息)o1.getTime()
return 是 long
。
Comparator#compareTo
returns一个int
;而 getTime
显然是 long
.
这样写比较好:
.sort(Comparator.comparingLong(Message::getTime))
拉姆达
lambda可以看做是shorthand有点笨重的匿名class:
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();
}
});
因此,每当您对如何编写正确的 lambda 感到困惑时,您可以尝试编写一个 pre-lambda 版本,看看它是如何错误的。
申请
在你的具体问题中,你可以看到compare
returns int
,其中你的getTime
returns long,这是错误的来源.
您可以使用任何一种方法作为其他回答方法,例如:
Long.compare(o1.getTime(),o2.getTime())
通知
- 您应该避免在
Comparator
中使用 -
,这在某些情况下可能会导致溢出并导致程序崩溃。
比较器
我们使用比较器接口对同类和异类元素进行默认的自定义排序顺序。
int compare(T o1, T o2);
it takes two arguments for ordering. Returns a
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.
Anonymous Classes how to sort a list of objects in prior versions of Java 8 使用内部 类.
匿名 class 无法访问其封闭范围内未声明为 final 或有效 final 的局部变量。
Comparator<Employee> timeCompare = new Comparator<Employee>() {
@Override public int compare(Employee e1, Employee e2) {
return e1.getCreationTime().compareTo( e2.getCreationTime() );
}
};
Java 8 Lambda Expressions
使用比较方法
A lambda expression is like a method: it provides a list of formal parameters and a body - an expression or block - expressed in terms of those parameters.
LambdaExpression: LambdaParameters -> LambdaBody
Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final, or a compile-time error occurs where the use is attempted.
Comparator<Employee> functional_semantics = (e1, e2) -> {
return e1.getCreationTime().compareTo( e2.getCreationTime() );
};
具有 Lambda 支持的基本排序
Comparator<Employee> timeCompareLambda = (o1, o2) -> (int) ( o1.getCreationTime() - o2.getCreationTime());
Collections.sort(java8, timeCompareLambda );
使用提取的密钥和Comparing method:通过提取的密钥进行比较的比较器。使用 :: 关键字传递引用。
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
}
另请参阅这些帖子:
- Java 8 Tutorial
- Java8 Lambdas vs Anonymous classes
- Lambda vs anonymous inner class performance
你应该改变
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()
方法必须 return 一个 int
,你的方法似乎是 returning long
。
您可以将其更改为:
Long.compare(o1.getTime(),o2.getTime())
在下面的视频中很好地解释了 lambda 比较器 link。
lamda 比较器
In the place of Developer write your class name
Comparator<Developer> byName =
(Developer o1, Developer o2)->o1.getName().compareTo(o2.getName());
我想用 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)
-> {})
Comparator
的 compare()
方法必须 return 一个 int
,你的似乎是 return 一个 long
。
您可以将其更改为:
(Message o1, Message o2)->Long.compare(o1.getTime(),o2.getTime())
这是假设(根据您的错误消息)o1.getTime()
return 是 long
。
Comparator#compareTo
returns一个int
;而 getTime
显然是 long
.
这样写比较好:
.sort(Comparator.comparingLong(Message::getTime))
拉姆达
lambda可以看做是shorthand有点笨重的匿名class:
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();
}
});
因此,每当您对如何编写正确的 lambda 感到困惑时,您可以尝试编写一个 pre-lambda 版本,看看它是如何错误的。
申请
在你的具体问题中,你可以看到compare
returns int
,其中你的getTime
returns long,这是错误的来源.
您可以使用任何一种方法作为其他回答方法,例如:
Long.compare(o1.getTime(),o2.getTime())
通知
- 您应该避免在
Comparator
中使用-
,这在某些情况下可能会导致溢出并导致程序崩溃。
比较器
我们使用比较器接口对同类和异类元素进行默认的自定义排序顺序。
int compare(T o1, T o2);
it takes two arguments for ordering. Returns a
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.
Anonymous Classes how to sort a list of objects in prior versions of Java 8 使用内部 类.
匿名 class 无法访问其封闭范围内未声明为 final 或有效 final 的局部变量。
Comparator<Employee> timeCompare = new Comparator<Employee>() {
@Override public int compare(Employee e1, Employee e2) {
return e1.getCreationTime().compareTo( e2.getCreationTime() );
}
};
Java 8 Lambda Expressions
使用比较方法
A lambda expression is like a method: it provides a list of formal parameters and a body - an expression or block - expressed in terms of those parameters.
LambdaExpression:
LambdaParameters -> LambdaBody
Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final, or a compile-time error occurs where the use is attempted.
Comparator<Employee> functional_semantics = (e1, e2) -> {
return e1.getCreationTime().compareTo( e2.getCreationTime() );
};
具有 Lambda 支持的基本排序
Comparator<Employee> timeCompareLambda = (o1, o2) -> (int) ( o1.getCreationTime() - o2.getCreationTime());
Collections.sort(java8, timeCompareLambda );
使用提取的密钥和Comparing method:通过提取的密钥进行比较的比较器。使用 :: 关键字传递引用。
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
}
另请参阅这些帖子:
- Java 8 Tutorial
- Java8 Lambdas vs Anonymous classes
- Lambda vs anonymous inner class performance
你应该改变
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()
方法必须 return 一个 int
,你的方法似乎是 returning long
。
您可以将其更改为:
Long.compare(o1.getTime(),o2.getTime())
在下面的视频中很好地解释了 lambda 比较器 link。
lamda 比较器
In the place of Developer write your class name
Comparator<Developer> byName =
(Developer o1, Developer o2)->o1.getName().compareTo(o2.getName());