1.从迭代到流的操作
在处理集合时,通常迭代遍历它的元素:
String contents = new String(Files.readAllBytes(Paths.get("alice30.txt")), StandardCharsets.UTF_8);
List<String> words = Arrays.asList(contents.split("\\PL+"));
long count = 0;
for (String w: words) {
if (w.length() > 12) {
count++;
}
}
在使用流时:
long count = words.stream().filter(w -> w.length() > 12).count();
流的版本比循环版本要更易于阅读,因为不必扫描整个代码去查找过滤和计数操作,方法名就可以直接看到代码意欲何为。
循环需要非常详细地指定操作的顺序,而流却能够以其想要的任何方式来调度这些操作,只要结果正确即可。
将stream修改为parallelStream就可以让流库以并行方式来执行过滤和计数。
流遵循了做什么而非怎么做的原则。
流和集合的显著差异:
1.流并不存储其元素。这些元素可能存储在底层的集合中,或者是按需生成。
2.流的操作不会修改其数据源。
3.流的操作尽可能惰性执行的。这意味着直至需要其结果时,操作才会执行。
实例代码:stream会产生一个用于words列表的stream,filter方法会返回另一个流,其中只包含长度大于12的单词。count方法会将这个流化简为一个结果。
操作流时典型的三个阶段的操作管道:
1.创建一个流
2.指定将初始化流转换为其他流的中间操作,可能包含多个步骤
3.应用终止操作,从而产生结果。这个操作会强制执行之前的惰性操作。从此之后,这个流就再也不能用了。
2.流的创建
数组可以用静态的Stream.of方法:
Stream<String> words = Stream.of(contents.split("\\PL+"));
of方法具有可变长参数,因此可以具有任意数量引元的流:
Stream<String> song = Stream.of("gently", "down", "the", "stream");
使用Array.stream(arry, from, to)可以数组中位于from(包括)和to(不包括)的元素中创建一个流。
Stream.empty创建不包含任何元素的流。
Stream接口有两个用于创建无限流的静态方法。generate方法会接受一个不包含任何引元的函数(从技术上讲,是一个Supplier< T >接口的对象)。只需要一个流类型的值,该函数就会调用用以产生一个这样的值。获取一个常量值的流:
Stream<String> echos = Stream.generate(() -> "Echo"); // 无限个Echo
获取一个随机数的流:
Stream<Double> randoms = Stream.generate(Math::random);
为了产生无限序列(0 1 2 3)可以使用iterate方法。它会接受一个种子值,以及一个函数(OnaryOperation< T >),并反复将该函数应用到之前的结果:
Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));
第一个元素是种子BigInteger.ZERO,第二个是f(seed),第三个是f(f(seed))。
Patteran类有一个splitAsStream方法,它会按照某个正则表达式来分割一个CharSequence对象:
Stream<String> ws = Pattern.compile("\\PL+").splitAsStream(contents);
静态的Files.lines方法会返回一个包含了文件所有行的Stream:
Stream<String> lines = Files.lines(Paths.get("alice30.txt"));
public class CreatingStreams {
public static <T> void show(String title, Stream<T> stream) {
final int SIZE = 10;
List<T> firstElements = stream.limit(SIZE + 1).collect(Collectors.toList());
System.out.println(title + ": ");
for (int i = 0; i < firstElements.size(); i++) {
if (i > 0) {
System.out.print(", ");
}
if (i < SIZE) {
System.out.print(firstElements.get(i));
} else {
System.out.print("...");
}
}
System.out.println();
}
public static void main(String[] args) throws IOException {
Path path = Paths.get("alice30.txt");
String contents = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
Stream<String> words = Stream.of(contents.split("\\PL+"));
show("words", words);
Stream<String> song = Stream.of("gently", "down", "the", "stream");
show("song", song);
Stream<String> echos = Stream.generate((