Java8 新特性之 Stream 实现排序

2,890 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情

1. Stream 排序操作

Java8 引入的 Stream 新特性可以方便的对集合进行相关处理,而在集合的操作中排序也是常见的一种,业务需求中往往有要求数据结果集合按照时间或数值的大小实现排序。

Stream 中提供了 sort() 方法来对流中的元素进行排序,要求元素所属类型必须实现 Comparable 接口。

sort() 方法是 Stream 的中间操作,排序完成后仍是是流数据,想要得到最终结果需要使用收集方法 .collect(Collectors.toList()) 得到最终集合类型。

2 简单 sort() 排序

sort() 方法是根据自然顺序对流中的元素进行排序

//自然排序(字符串类型按照首字母大小排序)
List<User> list = list.stream().sorted().collect(Collectors.toList());

除此之外,如果想要按照自然序列逆序排列,则 sort() 方法还可以配合 Comparator.reverseOrder() 实现

//自然排序的逆序
List<User> list = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

3. sorted(Comparator<? super T> comparator) 排序

sorted(Comparator com),Comparator 是一个比较器对象,这是一个函数式接口,可以通过实现排序方法来自定义排序结果。

sort() 方法可以通过 Comparator 提供的 reverseOrder() 来实现反序

list.stream().sorted(Comparator.reverseOrder())

3.2 传入 Comparable 表达式实现自定义排序

如果集合流中是对象,则进行排序时需要对象类实现 Comparable 接口,并重写其中的 compareTo() 来指定对象比较方式

public class User implements Comparable<User> {
    @Override
    public int compareTo(User o) {
        // 对象根据名称进行比较
        return name.compareTo(o.getName());
    }
}

// 正序
list.stream().sorted(Comparator.comparing(User::getAge));

// 倒序
list.stream().sorted(Comparator.comparing(User::getAge).reversed())
  • 如果要根据整个对象进行排序,还需要重写对象类的 equals() 方法和 hashCode() 方法

3.3 Map 容器排序

  1. 如果是 Map 容器,可以根据其 key 或者 value 排序
// 根据 key 排序
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue));

// 根据 value 排序
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey));

// 如果 map 的 value 是对象,则将根据对象来排序
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue));
  1. 对于使用字符串类型存储的数字,如果希望按照数字大小排序,则要增加排序规则
//comparing()方法中传入两个参数,一个是排序字段,一个是将其先转为整型
list.stream().sorted(Comparator.comparing(User::getSortCode, Comparator.comparingInt(Integer::parseInt)).reversed()).collect(Collectors.toList());
  • 根据对象的多个字段依次排序时使用 Comparator.comparing().thenComparing()

4. sorted() 排序实战

4.1 根据员工薪资排序

// 根据薪资排序
employeeList.stream().sorted(Comparator.comparing(Employee::getSalary))
    .collect(Collectors.toList());

4.2 先根据员工薪资,再根据年龄排序

// 先根据薪资,再根据年龄排序
employeeList.stream().sorted(Comparator.comparing(Employee::getSalary).thenComparing(Employee::getAge)).collect(Collectors.toList());

4.3 自定义排序规则,根据年龄排序(匿名类)

employeeList.stream().sorted(new Comparator<Integer>() {
    @Overide
    public int compare(Employee o1, Employee o2){
        return o1.getAge() - o2.getAge();
    }
}).collect(Collectors.toList());

4.3 自定义排序规则,根据年龄排序(Lambda 表达式)

employeeList.stream().sorted((o1,o2) -> {
    return p1.getAge() - p2.getAge();
}).collect(Collectors.toList());