我正在学习如何使用Java 8流。在调试这段代码时:
Collector<Person, StringJoiner, String> collector =
Collector.of(
() -> new StringJoiner(" | "),
(j,p) -> j.add(p.name.toLowerCase()),
StringJoiner::merge,
StringJoiner::toString);
System.out.println(persons.stream().collect(collector));
执行永远不会达到StringJoiner::merge
或StringJoiner::toString
。如果我用null替换组合器(StringJoiner::merge
),则代码抛出空指针异常。我无法跟进。
其他(相关)问题:
如何添加用于调试lambdas的日志记录?我尝试为多行代码块添加大括号。这不编译:
Collector<Person, StringJoiner, String> collector =
Collector.of(
() -> {
System.out.println("Supplier");
new StringJoiner(" | ")},
(j,p) -> j.add(p.name.toLowerCase()),
StringJoiner::merge,
StringJoiner::toString);
答案 0 :(得分:3)
这里添加了调试语句的代码(我用字符串替换了Person,但它没有改变任何东西):
List<String> persons = Arrays.asList("John", "Mary", "Jack", "Jen");
Collector<String, StringJoiner, String> collector =
Collector.of(
() -> {
System.out.println("Supplier");
return new StringJoiner(" | ");
},
(j, p) -> {
System.out.println("Accumulator");
j.add(p.toLowerCase());
},
(stringJoiner, other) -> {
System.out.println("Combiner");
return stringJoiner.merge(other);
},
(stringJoiner) -> {
System.out.println("Finisher");
return stringJoiner.toString();
});
System.out.println(persons.stream().collect(collector));
运行它,你会看到终结者被称为:
然而,组合器虽然需要检查null的方法of()
,但只有在并行流上使用收集器并且流确实决定在多个线程上拆分工作时才相关,因此使用多个连接器并将它们组合在一起。
为了测试这一点,你需要在集合中拥有大量人员,并且需要并行流而不是顺序流:
List<String> persons = new ArrayList<>();
for (int i = 0; i < 1_000_000; i++) {
persons.add("p_" + i);
}
Collector<String, StringJoiner, String> collector =
Collector.of(
() -> {
System.out.println("Supplier");
return new StringJoiner(" | ");
},
(j, p) -> {
System.out.println("Accumulator");
j.add(p.toLowerCase());
},
(stringJoiner, other) -> {
System.out.println("Combiner");
return stringJoiner.merge(other);
},
(stringJoiner) -> {
System.out.println("Finisher");
return stringJoiner.toString();
});
System.out.println(persons.parallelStream().collect(collector));
使用的线程数由流决定。如果它认为这是一个好主意,它可以将一个线程完成的任务分成中间的另外两个线程。我们假设它选择使用2: