java 8 之Streams 解说
基本概念
java 8新增的集合streams操作,简化了我们显示的遍历集合操作行为,而且提供内置的并发功能。
Streams操作中,如果操作产生的结果还是stream是lazy operation,但结果如果是void或者其他的value值则是eager operation,lazy operation做的目的是为了操作效率。
Streams的 api 中lazy operation类似我们常见的 建造者模式(Builder Pattern),以前我们是设置类的属性,这里我们设置的是行为。
代码示例:
package com.doctor.stream;
import java.util.List;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
/**
* @author sdcuike
*
* Created on 2016年6月10日 下午4:29:32
*
* It’s very easy to figure out whether an operation is eager or lazy: look at what it returns.
* If it gives you back a Stream, it’s lazy; if it gives you back another value or void, then it’s
* eager. This makes sense because the preferred way of using these methods is to form a
* sequence of lazy operations chained together and then to have a single eager operation
* at the end that generates your result.
*
* This whole approach is somewhat similar to the familiar builder pattern. In the builder
* pattern, there are a sequence of calls that set up properties or configuration, followed
* by a single call to a build method. The object being created isn’t created until the call
* to build occurs
*
* I’m sure you’re asking, “Why would we want to have the differentiator between lazy and
* eager options?” By waiting until we know more about what result and operations are
* needed, we can perform the computations more efficiently.
*/
public class StreamDemo {
public static void main(String[] args) {
List<String> names = Lists.newArrayList("doctor", "lily", "who", "doctor who");
List<String> result = names.stream().filter(e -> {
System.out.println("filter 1 :" + e);
return e.startsWith("do");
}).filter(e -> {
System.out.println("filter 2 :" + e);
return e.startsWith("doctor");
}).collect(Collectors.toList());
System.out.println("result:" + result);
}
}
执行结果:
filter 1 :doctor filter 2 :doctor filter 1 :lily filter 1 :who filter 1 :doctor who filter 2 :doctor who result:[doctor, doctor who]
由执行的结果,我们可以看出,Streams的filter操作是lazy operation,而collect操作是eager operation。
基本操作
1.collect(toList())
此操作是eager operation,从流中产生某种类型的数值列表。
List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList()); boolean equals = Arrays.asList("a", "b", "c").equals(list); Preconditions.checkState(equals); // true
2.map
我们经常需要将数据从一种形式转换到另一种形式的操作函数,而map操作就可以对流中的数据应用此函数,从而产生包含新值的数据流。
List<String> mapOperation = Stream.of("a", "b", "doctor who").map(String::toUpperCase).collect(Collectors.toList()); Preconditions.checkState(Arrays.asList("A", "B", "DOCTOR WHO").equals(mapOperation));
3.filter
可参考前面的代码例子。主要和以前我们写的if条件判断功能一样,过滤数据流中的数据功能。
4.flatMap
map操作,我们之前也看到了,它将流中的数据从一个类型转换到其他类型(非流类型),但如果我们将流中的数据转变成了流该如何操作,这时候我们就用到了 flatMap 操作,它会将产生的流合并成一个流继续下面的操作。
// flatMap lets you replace a value with a Stream and concatenates all the streams together. List<Integer> flatMapOperation = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4)).flatMap(e -> e.stream()).collect(Collectors.toList()); Preconditions.checkState(Arrays.asList(1, 2, 3, 4).equals(flatMapOperation));
5.max and min
这个操作很容易理解,就是找出列表数据中的最大值和最小值。
Integer max = Stream.of(1, 2, 66).max(Integer::compareTo).get(); Preconditions.checkState(max.equals(66));
6.reduce
当你想要对集合中的数据处理后得到唯一的结果时,我们借助 reduce操作。
int intValue = Stream.of(1, 2, 3).reduce(0, (acc, e) -> acc + e).intValue(); Preconditions.checkState(intValue == 6);
看一下java doc的说明:
Open Declaration Integer java.util.stream.Stream.reduce(Integer identity, BinaryOperator<Integer> accumulator) Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. This is equivalent to: T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result; but is not constrained to execute sequentially. The identity value must be an identity for the accumulator function. This means that for all t, accumulator.apply(identity, t) is equal to t. The accumulator function must be an associative function. This is a terminal operation. Parameters: identity the identity value for the accumulating function accumulator an associative, non-interfering, stateless function for combining two values Returns: the result of the reduction @apiNote Sum, min, max, average, and string concatenation are all special cases of reduction. Summing a stream of numbers can be expressed as: Integer sum = integers.reduce(0, (a, b) -> a+b); or: Integer sum = integers.reduce(0, Integer::sum); While this may seem a more roundabout way to perform an aggregation compared to simply mutating a running total in a loop, reduction operations parallelize more gracefully, without needing additional synchronization and with greatly reduced risk of data races.
时间: 2024-10-11 05:40:54