Java 8中使用Lambda对ArrayList进行排序

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)); 在函数式编程中,您不是使用旧对象对其

有人能给我举个例子,说明如何使用新的lambda语法在Java8中按字母顺序对
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"));