通常在开发程序时候都会对程序进行单步或设置断点调试代码. 而在 Java 8 中在使用 stream 时采用这种方式调试却与原有的方式稍有不同.
List<String> nations = Arrays.asList("A","B","C"); Set<String> nationalities = new HashSet<>(); for (String nation : nations) { if (nation.startsWith("A")) { System.out.println("Found nationality:" + nation); nationalities.add(nation); } }
上面这段代码, 当满足 if 条件时, 我们可以将满足条件的结果输出, 以验证程序是否正确执行. 若通过 Java 8 中的 stream 来改写上述操作, 代码如下.
nations.stream().filter((s) -> s.startsWith("A")).forEach( nationality -> System.out.println("Found:" + nationality));
我们通过 forEach 来输出过滤后的结果. 然而这样做, 将无法再继续在这个流上进行操作. 如果还想继续对该流进行操作, 那么需要重新建立这个流. 例如还希望进行 map 操作并观察结果.
nations.stream().filter((s) -> s.startsWith("A")).map((param) -> param + "/").forEache(nationality -> System.out.println("Found:" + nationality));
为了观察中间结果, 便于调试改错, 我们可以通过 peek 方法来完成.
List<String> nations = Arrays.asList("A","B","C","A1"); nations.stream(). filter(nation -> { return nation.startsWith("A"); }). peek(nation -> System.out.println(nation)). map((t) -> { return t + "a"; }). peek(nation -> System.out.println(nation)). collect(Collectors.toList());
这样便可以观察每一步的中间结果.
此外我们还可以通过设置断点的方式来观察结果.
注意, stream 中的 map 属于惰性操作 (Lazy operation), 即当终结操作发生后才会执行 map,filter 同理. 在这里终结是指 collect. 此外在设置断点时需要将 stream 调用的方法分多行写出, 例如上图所示. 通过上述方法可以观察 Stream 中的结果, 进行代码调试.
参考
- http://stackoverflow.com/questions/24541786/how-to-debug-stream-map-with-lambda-expressions
- Java 8 lambda,Chapter7
来源: https://juejin.im/entry/5b08bc21f265da0dca10a240