java基础-函数式编程 (5)

Stream还有一个强大的分组功能,可以按组输出。我们看下面的例子:

import java.util.*; import java.util.stream.*; public class Main { public static void main(String[] args) { List<String> list = List.of("Apple", "Banana", "Blackberry", "Coconut", "Avocado", "Cherry", "Apricots"); Map<String, List<String>> groups = list.stream() .collect(Collectors.groupingBy(s -> s.substring(0, 1), Collectors.toList())); System.out.println(groups); } }

分组输出使用Collectors.groupingBy(),它需要提供两个函数:

一个是分组的key,这里使用s -> s.substring(0, 1),表示只要首字母相同的String分到一组,

第二个是分组的value,这里直接使用Collectors.toList(),表示输出为List,上述代码运行结果如下:

{ A=[Apple, Avocado, Apricots], B=[Banana, Blackberry], C=[Coconut, Cherry] } 3.6 其他操作 排序

(是转化操作)

对Stream的元素进行排序十分简单,只需调用sorted()方法:

import java.util.*; import java.util.stream.*; public class Main { public static void main(String[] args) { List<String> list = List.of("Orange", "apple", "Banana") .stream() .sorted() .collect(Collectors.toList()); System.out.println(list); } }

Comparable接口

此方法要求Stream的每个元素必须实现Comparable接口。如果要自定义排序,传入指定的Comparator即可:

List<String> list = List.of("Orange", "apple", "Banana") .stream() .sorted(String::compareToIgnoreCase) .collect(Collectors.toList());

注意sorted()只是一个转换操作,它会返回一个新的Stream

去重

对一个Stream的元素进行去重,没必要先转换为Set,可以直接用distinct():

List.of("A", "B", "A", "C", "B", "D") .stream() .distinct() .collect(Collectors.toList()); // [A, B, C, D] 截取

是转换操作

截取操作常用于把一个无限的Stream转换成有限的Stream,
skip()用于跳过当前Stream的前N个元素,
limit()用于截取当前Stream最多前N个元素:

List.of("A", "B", "C", "D", "E", "F") .stream() .skip(2) // 跳过A, B .limit(3) // 截取C, D, E .collect(Collectors.toList()); // [C, D, E]

截取操作也是一个转换操作,将返回新的Stream。

合并

将两个Stream合并为一个Stream可以使用Stream的静态方法concat():

Stream<String> s1 = List.of("A", "B", "C").stream(); Stream<String> s2 = List.of("D", "E").stream(); // 合并: Stream<String> s = Stream.concat(s1, s2); System.out.println(s.collect(Collectors.toList())); // [A, B, C, D, E] flatMap

指把Stream的每个元素(这里是List)映射为Stream,然后合并成一个新的Stream:

例子:如果Stream的元素是集合:

Stream<List<Integer>> s = Stream.of( Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9));

而我们希望把上述Stream转换为Stream,就可以使用flatMap():

Stream<Integer> i = s.flatMap(list -> list.stream()); 并行

通常情况下,对Stream的元素进行处理是单线程的,即一个一个元素进行处理。但是很多时候,我们希望可以并行处理Stream的元素,因为在元素数量非常大的情况,并行处理可以大大加快处理速度。

把一个普通Stream转换为可以并行处理的Stream非常简单,只需要用parallel()进行转换:

Stream<String> s = ... String[] result = s.parallel() // 变成一个可以并行处理的Stream .sorted() // 可以进行并行排序 .toArray(String[]::new); 其他聚合方法

测试Stream的元素是否满足以下条件:

boolean allMatch(Predicate):测试是否所有元素均满足测试条件;

boolean anyMatch(Predicate):测试是否至少有一个元素满足测试条件。

最后一个常用的方法是forEach(),它可以循环处理Stream的每个元素,我们经常传入System.out::println来打印Stream的元素:

Stream<String> s = ... s.forEach(str -> { System.out.println("Hello, " + str); }); 小结

Stream提供的常用操作有:

转换操作:

map(),给定规则转换

filter(),给定规则过滤

sorted(),排序

distinct();去重

聚合操作:

reduce(),聚合

collect(),输出集合

count(),元素计数

max(),找出最大元素

min(),找出最小元素

sum(),针对IntStream、LongStream和DoubleStream元素求和

average(),针对IntStream、LongStream和DoubleStream元素求平均

合并操作:concat(),flatMap();

并行处理:parallel();

其他操作:allMatch(), anyMatch(), forEach()。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zypzyy.html