我正在研究Java8 esp Stream API。 但仍然没有得到流和地图的工作方式。
我对流的理解就像 当我使用peek()和forEach()时,结果将是1111 2222,但println()的结果是混合的。
我想如果我使用map()。filter()。map()。filter()然后首先执行map()并返回流并执行下一个filter()并像这样移动到下一个。所以我对这个结果很困惑。
这是我的代码
package exam_20170823;
import java.io.File;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamEx2 {
public static void main(String[] args) {
File[] fileArr = {
new File("Ex1.java"),
new File("Ex1.bak"),
new File("Ex1.txt"),
new File("Ex2.java"),
new File("Ex1")
};
/*1) make stream
2) find filename extension
3) change 2) to uppercase
4) remove duplicate
5) print
*/
Stream<File> fileStream = Stream.of(fileArr);
fileStream.map(s->s.getName())
.filter(s -> s.indexOf(".") != -1)
.peek(a -> System.out.println(a))
.map(s -> s.substring(s.indexOf(".")+1).toUpperCase())
.distinct()
.forEach(s -> System.out.println(s));
}
}
这是结果
Ex1.java
JAVA
Ex1.bak
BAK
Ex1.txt
TXT
Ex2.java
我想知道为什么结果不是这样的? - &GT; “Ex1.java,Ex1.bak,Ex1.txt,Ex2.java”首先打印“JAVA,BAK,TXT”
我首先使用peek(),最后使用foreach(),所以我期待
使用peek()后,流将为Ex1.java,Ex1.bak,Ex1.txt,Ex2.java
接下来我使用map()所以它必须有JAVA,BAK,TXT
。和
最后使用foreach()所以流的每一个东西都会打印出我所期望的东西,但它太混乱了。有谁能帮我理解为什么?
答案 0 :(得分:3)
我觉得你在这里混淆了懒惰。不所有元素将通过map
,然后全部通过 filter
,然后所有被过滤的元素将转到另一个map
1}}。这不是流的工作方式。
处理懒惰。这意味着一次一个元素来自source
(在您的情况下是File
s的数组),那么该元素将遍历Stream管道的所有阶段(map
,然后是filter
,然后是peek
);请注意,如果filter
失败,则根本不会达到peek
。然后第二个元素从源中获取并执行相同的操作,依此类推。
这就是为什么你一次看到每个舞台上的输出。见这个例子:
Stream.of(1, 2, 3, 4)
.filter(x -> {
System.out.println("Filering x = " + x);
return x > 2;
})
.map(x -> {
System.out.println("Mapping x = " + x);
return x + 1;
})
.collect(Collectors.toList());
注意mapping
阶段仅在第三个元素上执行,因为前两个不满足Predicate
阶段中的filter
。