List<String> words = Arrays.asList("Banana", "Orange", "Apple", "Lemon");
words.stream()
.sorted()
.forEach(System.out::println); // Apple, Banana, Lemon, Orange
这里的排序是基于字符串的自然顺序,即字典序。非常简单易懂,对吧?
但世界上总是充满多样性,我们的需求往往不止于此。如果我想按照字符串的长度来排序怎么办?这时候就需要定制排序了。sorted 方法接受一个 Comparator 参数,让我们可以定义自己的排序逻辑。
List<String> words = Arrays.asList("Banana", "Orange", "Apple", "Lemon", "Cherry");
words.stream()
.sorted((s1, s2) -> s1.length() - s2.length())
.forEach(System.out::println); // Apple, Lemon, Banana, Orange, Cherry
在这个例子中,我们基于字符串的长度进行排序,结果是按长度从小到大排列的。
Comparator的链式调用
有时候,一个排序条件不够用,我们可能要根据多个条件进行排序。好在 Comparator 具有链式调用的能力,允许我们优雅地完成这一需求。
List<String> words = Arrays.asList("banana", "Orange", "apple", "Lemon");
words.stream()
.sorted(Comparator.comparingInt(String::length)
.thenComparing(String::toLowerCase))
.forEach(System.out::println); // apple, Lemon, banana, Orange
在这个例子中,我们首先按照字符串长度进行排序,长度相同的情况下,再按照字典序排序。注意到字母大小写对结果的影响,利用 toLowerCase 实现了忽略大小写的排序。
最后,如果我们希望逆转排序的顺序,Comparator 提供的 reversed() 方法派上用场了。就像是时间的倒流,给定的排序逻辑在此刻被逆转。
List<String> words = Arrays.asList("Banana", "Orange", "Apple", "Lemon", "Cherry");
words.stream()
.sorted(Comparator.comparing(String::length).reversed())
.forEach(System.out::println); // Cherry, Banana, Orange, Apple, Lemon
在这个例子中,我们首先根据字符串长度进行排序,然后调用 reversed() 方法,实现了长度从大到小的逆序排列。
通过上面这些例子,你可以看到,Java Stream API 中的 sorted 方法及 Comparator 接口提供了强大而灵活的排序机制。无论是简单的自然排序,还是复杂的多条件排序,甚至是逆序排序,Stream 都能轻松应对,这正是Java流式处理的魅力所在。
利用收集器进行数据收集
讲了这么多,我们终于来到了Stream API的一个非常强大功能——收集器(Collectors)。通过collect方法结合各种收集器,我们能够轻松实现对流数据的汇总、分组、分片等复杂操作。这简直就是魔法中的魔法,让数据处理效率和可读性都质的飞跃:
// 收集到List
List<Integer> list = stream.collect(Collectors.toList());
// 分组
Map<Integer, List<String>> groups = stream.collect(Collectors.groupingBy(String::length));
// 字符串连接
String result = stream.collect(Collectors.joining(", "));
最后,如果你想要更快处理你的数据,Stream还提供了并行处理的能力。通过简单地调用parallelStream()代替stream(),或是在一个流上调用.parallel(),你就能让你的数据处理逻辑自动并行化运行,利用多核处理器加速你的数据处理过程。
List<String> list = Arrays.asList("Java", "Stream", "Magic");
// 创建并行流
Stream<String> parallelStream = list.parallelStream();
最后,记住,使用Stream魔法的时候,不要忘了调用终端操作,比如collect、forEach或者reduce,因为只有在进行了终端操作之后,所有的中间操作才会被执行。
Published in
Java