首页 > 代码库 > Java8 Stream API
Java8 Stream API
Stream是Java8中,操作集合的一个重要特性。
从iteration到Stream操作
当你操作一个集合的时候,你通常的做法是迭代每一个元素,然后处理你想要的事情。举个例子:
String contents = new String(Files.readAllBytes( Paths.get("alice.txt")), StandardCharsets.UTF_8); // 读取文件到字符串中List<String> words = Arrays.asList(contents.split("[\\P{L}]+")); // 截取words
现在我们来迭代操作它:
int count=0;for (String w : words) { if (w.length() > 12) count++;}
这段代码有什么问题吗?除了并行处理不是很好以为我想是没有。在Java8中,相同的操作是这么处理的:
long count = words.stream().filter(w -> w.length() > 12).count();
so cool!从代码中,我们就能非常容易的看出它要表达的意思,filter是针对words的过滤。
有人会问,这样的操作的确让人很是兴奋,但是刚才说到的并行处理它能解决吗?答案是不可以,但是Java8给我们提供了非常好的API,并行处理如下:
long count = words.parallelStream().filter(w -> w.length() > 12).count();
通过将stream()修改为parallelStream(),这样就可以并行的进行过滤和统计了。
从表面上,stream看起来和集合很像,你可以自由的操作它。但是有以下几点不同:
- stream不存储集合元素
- stream操作不修改源数据,他们是返回一个新的streams来承载结果
- stream操作都会尽可能的进行延迟加载。这意味着当需要使用结果的时候它才会才运行。
当你使用stream的时候,需要关注一下3个阶段:
- 创建一个stream
- 指定的中间操作将初始stream转化为其他stream
- 最终的操作会产生一个结果,在调用最终操作前都会延迟执行的。在这之后,stream不会再被使用。
在上面的例子中,stream()和parallelStream()创造了stream,filter方法转化了它,count方法是最终的操作。
注意:stream操作不是按照引用的顺序来执行的。在例子中,知道count调用才执行。当count方法请求第一个元素,filter方法开始请求元素,知道找到一个长度大于12的元素。
Stream创建
Java8中,你就可以将集合的操作都利用stream来处理,如果你有一个数组,使用静态的Stream.of方法来实现:
// 分隔后返回String[]Stream<String> words = Stream.of(content.split("[\\P{L}]+"));
of方法定义:
public static<T> Stream<T> of(T t);public static<T> Stream<T> of(T... values);
所以你可以构造很多参数的stream。
使用Arrays.stream(array, from, to),可以得到数组的一部分。
想要创建一个空的stream,可以使用Stream.empty方法:
Stream<String> silence = Stream.empty();
stream接口有2个静态方法来构造无限的streams。generate方法是通过无参函数的。比如:
Stream<String> echos = Stream.generate(() -> "Echo");orStream<Double> randoms = Stream.generate(Math::random);
如果想要产生一个无限的序列,例如:0 1 2 3 ...,可以使用iterate方法来实现:
Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));
filter.map和flatMap方法
待续,有没有期待?