Java 8中使用Lambda对ArrayList进行排序
有人能给我举个例子,说明如何使用新的lambda语法在Java8中按字母顺序对Java 8中使用Lambda对ArrayList进行排序,java,lambda,functional-programming,java-8,Java,Lambda,Functional Programming,Java 8,有人能给我举个例子,说明如何使用新的lambda语法在Java8中按字母顺序对ArrayList进行排序。您只是在排序字符串吗?如果是这样,你就不需要lambdas;没有意义。你就是这样 import static java.util.Comparator.*; list.sort(naturalOrder()); …不过,如果您使用字符串字段对对象进行排序,那么它会更有意义: list.sort(comparing(Foo::getString)); 在函数式编程中,您不是使用旧对象对其
ArrayList进行排序。您只是在排序字符串吗?如果是这样,你就不需要lambdas;没有意义。你就是这样
import static java.util.Comparator.*;
list.sort(naturalOrder());
…不过,如果您使用字符串
字段对对象进行排序,那么它会更有意义:
list.sort(comparing(Foo::getString));
在函数式编程中,您不是使用旧对象对其进行操作,而是以这种方式创建新对象:
list.stream().sorted().map(blah-blah).filter(...)...
对于字符串,这将起作用
arrayList.sort((p1, p2) -> p1.compareTo(p2));
使用list.sort(String::compareToIgnoreCase)
使用list.sort(String::compareTo)
或list.sort(Comparator.naturalOrder())
将给出不正确的(即非字母顺序的)结果。它将在所有小写字母之前对任何大写字母进行排序,因此数组[“aAAA”,“Zzz”,“Zzz”]
将排序为[“Zzz”,“aAAA”,“Zzz”]
假设您有要按字母顺序排序的名称(字符串)列表
List<String> result = names.stream().sorted(
Comparator.comparing(n->n.toString())).collect(Collectors.toList());
List result=names.stream().sorted(
Comparator.comparing(n->n.toString()).collect(collector.toList());
它工作得很好。一个真正通用的解决方案是引入一些类似的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));
}
}
最简明的:
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);
List myList=new ArrayList();
myList.添加(“A”);
myList.添加(“D”);
myList.添加(“C”);
myList.添加(“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);
类用户{
双倍得分;
//构造函数//获取器//设置器
}
列表用户=新建ArrayList();
添加(新用户(19d));
添加(新用户(67d));
添加(新用户(50d));
添加(新用户(91d));
列表分拣机=用户
.stream()
.sorted(Comparator.comparing(用户::getScore))
.collect(Collectors.toList());
分拣机.forEach(系统输出::println);
如果排序更复杂,则必须编写自己的比较器并将其传入。List List=new ArrayList();
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);
}
List list1=新的ArrayList();
列表.增加(新产品(1));
列表.增加(新产品(2));
列表.增加(新产品(3));
列表.增加(新产品(10));
Collections.sort(list,Comparator.comparing((产品p)->p.id));
用于(产品p:列表){
系统输出打印项次(p.id);
}
Lambdas不应该成为目标。在您的情况下,可以使用与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)
,但我不建议这样做,因为它不是类型安全的。包含自定义比较器的语法非常简单、快速,例如,这里正在排序的ArrayList包含JSONObject,我将根据名为“order”的属性对其进行排序:
arrayList.sort((JSONObject o1, JSONObject o2)->o1.getInt("order")-o2.getInt("order"));
我认为这是一种非常好的简洁语法,易于阅读,并且比非lambda语法体积更小。我建议您阅读:更好:arrayList.sort(String::compareTo)甚至更好:请注意,.sort(String::compareTo)和.sort(Comparator.naturalOrder())将在任何小写字母之前对所有大写字母进行排序。通常您需要的是.sort(String::compareToIgnoreCase)
这是不正确的,因为现在流不再由旧元素组成,而是由映射和过滤版本组成。考虑一个你想按人名排序的银行账户:如果你按照你的建议去做,那么你就开始使用一个银行账户,最后用一个人名流来结束,同时你想再次得到一个银行账户。一般来说,当你用FP风格写你的程序时,你不需要反复保存结果。因此,这一切都是一个新列表:list.stream().sorted()不是对旧列表进行排序,而是创建新列表。该列表已经变得毫无用处,因为您只剩下此人的姓名(在我的示例中),并且您无法再(直接)将其引用回他们的银行帐户。此外,可能也是您的困惑的根源(无需责备),OP请求了一个方法来对列表进行排序,但是您只返回一个中间流,您还需要在某个点存储它,您在回答中忽略了这一点。通过尝试实现这一点,您自己也可能会看到问题。@skiwi不需要指定排序运算符,因为OP希望按字典顺序对字符串
进行排序,这是默认行为。比较器
完全不需要。坚持函数式编程,例如(产品p:list){System.out.println(p.id);}可以写成list.stream().forEach(System.out::println);
arrayList.sort((JSONObject o1, JSONObject o2)->o1.getInt("order")-o2.getInt("order"));