Java Stream collect()方法示例
Java Stream collect()对流的元素执行可变的约简操作。
这是终端操作。
什么是可变归约运算?
可变还原操作处理流元素,然后将其累积到可变结果容器中。
处理完元素后,合并功能将合并所有结果容器以创建结果。
Java Stream collect()方法签名
Java Stream collect()方法有两种变体。
- <R> R收集(供应商<R>供应商,BiConsumer <R 、?超级T>累加器,BiConsumer <R,R>组合器)
- <R,A> R收集器(Collector <?super T,A,R>收集器)
收集器是一个接口,为供应商,累加器和组合器对象提供包装。
当我们利用Collectors类提供内置的Collector实现时,第二种方法很有用。
collect()函数的三个参数是:
供应商:创建新的可变结果容器的函数。
对于并行执行,可以多次调用此函数,并且每次必须返回一个新值。累加器是一种无状态函数,必须将元素折叠到结果容器中。
组合器是一个无状态函数,它接受两个部分结果容器并将其合并,这些容器必须与累加器功能兼容。
流collect()方法示例
我们来看一些Stream.collect()方法的示例。
1.串联字符串列表
假设您要连接字符串列表以创建新字符串。
我们可以使用Stream collect()函数执行可变的约简操作并连接列表元素。
List<String> vowels = List.of("a", "e", "i", "o", "u"); //sequential stream - nothing to combine StringBuilder result = vowels.stream().collect(StringBuilder::new, (x, y) -> x.append(y), (a, b) -> a.append(",").append(b)); System.out.println(result.toString()); //parallel stream - combiner is combining partial results StringBuilder result1 = vowels.parallelStream().collect(StringBuilder::new, (x, y) -> x.append(y), (a, b) -> a.append(",").append(b)); System.out.println(result1.toString());
输出:
aeiou a,e,i,o,u
供应商函数在每次调用中都返回一个新的StringBuilder对象。
累加器功能将列表字符串元素附加到StringBuilder实例。
合并器功能正在合并StringBuilder实例。
实例彼此之间用逗号合并。在第一种情况下,我们有一个顺序的元素流。
因此,它们被一个接一个地处理,并且只有一个StringBuilder实例。
没有使用合并器功能。
这就是为什么产生的输出是" aeiou"的原因。在第二种情况下,我们有并行的字符串流。
因此,元素是并行处理的,并且组合器函数正在合并StringBuilder的多个实例。
因此,产生的输出为" a,e,i,o,u"。如果流源是按顺序排序的,例如List,则collect()方法将在处理时保持顺序。
如果流源是无序的(例如Set),则collect()方法在每次调用中会产生不同的结果。
如果要串联字符串列表,我们可以使用方法引用来减少代码大小。
String result2 = vowels.parallelStream() .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) .toString();
2.使用collectors类将collect()流传输到列表
Collector类提供了Collector接口的许多有用的实现。
让我们看一个示例,其中我们将过滤整数列表以仅选择偶数整数。
Stream filter()是一个中间操作,返回一个流。
因此,我们将使用collect()函数从此流中创建列表。
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); List<Integer> evenNumbers = numbers.stream().filter(x -> x % 2 == 0).collect(Collectors.toList()); System.out.println(evenNumbers); //[2, 4, 6]
Collectors.toList()返回一个Collector实现,该实现将输入元素累积到新的List中。
3.流collect()到集合
我们可以使用Collectors.toSet()将流元素收集到一个新的Set中。
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); Set<Integer> oddNumbers = numbers.parallelStream().filter(x -> x % 2 != 0).collect(Collectors.toSet()); System.out.println(oddNumbers); //[1, 3, 5]
3.流collect()到Map
我们可以使用Collectors.toMap()函数将流元素收集到Map中。
此方法接受两个用于映射键的参数和Map中的对应值。
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6); Map<Integer, String> mapOddNumbers = numbers.parallelStream().filter(x -> x % 2 != 0) .collect(Collectors.toMap(Function.identity(), x -> String.valueOf(x))); System.out.println(mapOddNumbers); //{1=1, 3=3, 5=5}
4.收集器join()示例
我们可以使用Collectors join()方法来获取Collector,该Collector以遭遇顺序连接输入流CharSequence元素。
我们可以使用它来连接字符串流,StringBuffer或者StringBuilder。
jshell> String value = Stream.of("a", "b", "c").collect(Collectors.joining()); value ==> "abc" jshell> String valueCSV = Stream.of("a", "b", "c").collect(Collectors.joining(",")); valueCSV ==> "a,b,c" jshell> String valueCSVLikeArray = Stream.of("a", "b", "c").collect(Collectors.joining(",", "{", "}")); valueCSVLikeArray ==> "{a,b,c}" jshell> String valueObject = Stream.of("1", new StringBuffer("2"), new StringBuilder("3")).collect(Collectors.joining()); valueObject ==> "123"