背景
朋友今天面试,被面试官问到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());
总结
- 实现Comparable接口
- 传入Comparator对象