【发布时间】:2014-07-05 07:11:57
【问题描述】:
有人可以向我展示一个简单的示例,如何使用新的 lambda 语法在 Java 8 中按字母顺序对 ArrayList 进行排序。
【问题讨论】:
标签: java lambda functional-programming java-8
有人可以向我展示一个简单的示例,如何使用新的 lambda 语法在 Java 8 中按字母顺序对 ArrayList 进行排序。
【问题讨论】:
标签: java lambda functional-programming java-8
对于字符串,这会起作用
arrayList.sort((p1, p2) -> p1.compareTo(p2));
【讨论】:
.sort(String::compareTo) and .sort(Comparator.naturalOrder()) 都会将 all 大写字母排在任何小写字母之前。通常你想要的是.sort(String::compareToIgnoreCase)
您只是在对Strings 进行排序吗?如果是这样,您不需要 lambda;毫无意义。你只是这样做
import static java.util.Comparator.*;
list.sort(naturalOrder());
...虽然如果您使用 String 字段对对象进行排序,那么它会更有意义:
list.sort(comparing(Foo::getString));
【讨论】:
使用list.sort(String::compareToIgnoreCase)
使用list.sort(String::compareTo) 或list.sort(Comparator.naturalOrder()) 会给出不正确(即非字母)的结果。它将在 all 小写字母之前对 any 大写字母进行排序,因此数组 ["aAAA","Zzz", "zzz"] 被排序为 ["Zzz", "aAAA", "zzz"]
【讨论】:
假设您有想要按字母顺序排序的名称列表(字符串)。
List<String> result = names.stream().sorted(
Comparator.comparing(n->n.toString())).collect(Collectors.toList());
它工作得很好。
【讨论】:
Comparator 完全不需要。
在函数式编程中,您不是使用旧对象来操作它们,而是以这种方式创建新对象:
list.stream().sorted().map(blah-blah).filter(...)...
【讨论】:
Strings 进行排序,这是默认行为。
Lambda 不应该是目标。在您的情况下,您可以像在 Java 1.2 中一样对其进行排序:
Collections.sort(list); // case sensitive
Collections.sort(list, String.CASE_INSENSITIVE_ORDER); // case insensitive
如果你想用 Java 8 的方式来做:
list.sort(Comparator.naturalOrder()); // case sensitive
list.sort(String.CASE_INSENSITIVE_ORDER); // case insensitive
您也可以使用list.sort(null),但我不建议这样做,因为它不是类型安全的。
【讨论】:
一个真正通用的解决方案是引入一些 StreamUtil 之类的
public class StreamUtil {
private StreamUtil() {
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <TYPE> Comparator<TYPE> sort(Function<TYPE, ? extends Comparable> getterFunction, boolean descending) {
if (descending) {
return (o1, o2) -> getterFunction.apply(o2).compareTo(getterFunction.apply(o1));
}
return (o1, o2) -> getterFunction.apply(o1).compareTo(getterFunction.apply(o2));
}
}
调用看起来像
list.stream().sorted(sort(YourClass::getSortProperty, true));
【讨论】:
最简洁:
Collections.sort(stringList, String::compareToIgnoreCase);
【讨论】:
如果您有一个包含自然排序元素的数组(即String、int、double);那么可以通过以下方式实现:
List<String> myList = new ArrayList<>();
myList.add("A");
myList.add("D");
myList.add("C");
myList.add("B");
myList.sort(Comparator.comparing(s -> s));
myList.forEach(System.out::println);
另一方面,如果您有一个对象数组,并且您想根据某种对象字段进行排序,那么您可以使用:
class User {
double score;
// Constructor // Getters // Setters
}
List<User> users = new ArrayList<>();
users.add(new User(19d));
users.add(new User(67d));
users.add(new User(50d));
users.add(new User(91d));
List<User> sortedUsers = users
.stream()
.sorted(Comparator.comparing(User::getScore))
.collect(Collectors.toList());
sortedUsers.forEach(System.out::println);
如果排序更复杂,那么您必须编写自己的比较器并将其传入。
【讨论】:
List<Product> list = new ArrayList<>();
List<String> list1 = new ArrayList<>();
list.add(new Product(1));
list.add(new Product(2));
list.add(new Product(3));
list.add(new Product(10));
Collections.sort(list, Comparator.comparing((Product p) -> p.id));
for (Product p : list) {
System.out.println(p.id);
}
【讨论】:
包含自定义比较器的语法非常简单快捷,例如这里被排序的 ArrayList 包含 JSONObjects,我将根据名为“order”的属性对其进行排序:
arrayList.sort((JSONObject o1, JSONObject o2)->o1.getInt("order")-o2.getInt("order"));
我认为这是一种非常简洁明了的语法,易于阅读并且比非 lambda 语法更简洁。
【讨论】: