Stream流里面是如何排序的,如何实现多个字段排序?

276 阅读1分钟

背景

朋友今天面试,被面试官问到Stream流的排序,他直言面试官SX,问这么低级的问题,但是作为听众的我停下来思考了一下,好像平时确实只是用IDEA自动提示,咔咔代码就敲好了,也没有自己想想,到底是如何实现的,所以才有了这篇文章。

What Stream流怎么排序

先来一段Demo

public class Demo {

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class User{
        Integer age;

        String name;
    }

    public static void main(String[] args) {
        List<User> user = Arrays.asList(new User(18,"小明"),new User(28,"小花"),new User(2,"小李"));

        List<User> sortedUser = user.stream().sorted().collect(Collectors.toList());

        System.out.println(JSON.toJSONString(sortedUser));
    }


}

大部分的同学可能觉得没啥问题,有没有思考一下,哪我直接sorted,到底是如何排序的呢,这段代码最终的执行如下:

Exception in thread "main" java.lang.ClassCastException: com.example.demojar.diff.Demo$User cannot be cast to java.lang.Comparable
	at java.util.Comparators$NaturalOrderComparator.compare(Comparators.java:47)
	at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
	at java.util.TimSort.sort(TimSort.java:220)
	at java.util.Arrays.sort(Arrays.java:1512)
	at java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:348)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:483)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
	at com.example.demojar.diff.Demo.main(Demo.java:31)

直接异常了,说你排序的对象无法强制转换成Comparable。

所以但凡用到Stream的对象要么实现Comparable,要么在sorted()的时候传入Comparetor对象告诉Stream如何排序。

方案一: 实现Comparable接口

@Data
@NoArgsConstructor
@AllArgsConstructor
static class User implements Comparable<User> {
    Integer age;

    String name;

    @Override
    public int compareTo(User o) {
        // 按照年龄排序 从小到大排序
        return this.age.compareTo(o.age);
    }
}

方案二: 排序传入Comparator

user.stream().sorted(Comparator.comparing(u -> u.age)).collect(Collectors.toList());

总结

  1. 实现Comparable接口
  2. 传入Comparator对象