在Java流中,使用.peek()被视为仅用于调试目的,日志记录会被视为调试吗?

时间:2019-01-28 05:56:27

标签: java java-8 java-stream

因此,我有一个列表,希望处理部分或全部对象,并希望记录处理过的对象。

考虑一个虚构的例子:

auth_to_local

在这种情况下使用.peek()是否会被视为对API的意外使用?

为进一步说明,在this question中,关键要点是:“即使实现了您的近期目标,也不要以意外的方式使用API​​。” 或不是每次使用peek,除非您调试流,直到您确认整个链条均按设计要求工作并再次删除.peek(),否则这是意外使用。因此,如果将其用作记录流实际处理的每个对象的方式,则被视为意外使用。

4 个答案:

答案 0 :(得分:2)

应避免使用窥视,因为某些终端操作可能不会被称为窥视,请参见this answer。在该示例中,最好在forEach的动作内部进行日志记录,而不是使用peek。在这种情况下进行调试意味着使用临时代码来修复错误或诊断问题。

答案 1 :(得分:2)

documentation of peek将意图描述为

  

此方法主要用于支持调试,您希望在其中查看元素流过管道中特定点的情况。

.peek(classInSchool -> log.debug("Processing classroom {} in sixth grade without classroom.", classInSchool)形式的表达式满足了此意图,因为它与报告元素的处理有关。不管使用日志记录框架还是仅使用打印语句都没关系,如文档示例.peek(e -> System.out.println("Filtered value: " + e))中所示。在这两种情况下,意图都至关重要,而不是技术方法。如果有人使用peek打印所有元素,那将是错误的,即使它使用了与文档示例(System.out.println)相同的技术方法。

文档并没有要求您必须区分生产环境或调试环境,而不必删除前者的peek用法。实际上,您的使用甚至可以满足要求,因为日志记录框架允许您通过可配置的日志记录级别使该操作静音。

我仍然建议记住,对于某些管道,插入peek操作可能会比实际操作插入更多开销(或在某种程度上阻碍JVM的循环优化)。但是,如果您没有遇到性能问题,则可以遵循旧的建议,除非有充分的理由,否则不要尝试进行优化……

答案 2 :(得分:1)

  

在使用.peek()的java流中,仅将其用于调试目的,将日志记录视为调试对象吗?

这取决于您的日志记录代码是否将永久保留为代码。

只有您才能真正了解日志记录的真正目的...

还要注意,javadoc表示:

  

在流实现能够优化某些或所有元素的产生的情况下(例如使用findFirst之类的短路操作,或在count()中描述的示例中),这些元素将不会调用该操作。

因此,您可能会发现在某些情况下peek并不是记录(或调试)管道的可靠方法。

通常,添加peek可能会改变管道的行为和/或JVM在当前或下一代JVM中对其进行优化的能力。

答案 3 :(得分:0)

嗯,有些解释是开放的。意图并非总是容易确定的。

我认为添加API注释主要是为了避免过度使用peek时几乎不需要的行为就可以完成。对于开发人员来说,完全排除它实在太有用了,但是他们想清楚,它的 inclusion 不应被视为不合格的认可;他们看到了滥用的可能性,并试图解决。

我怀疑-尽管我只是猜测-关于是否要完全包含它,并且在JavaDoc中包含带有警告的版本存在妥协。

考虑到这一点,我认为我决定何时使用peek的建议只是:除非您有充分的理由,否则不要使用它。

对于您而言,您绝对没有充分的理由。您正在遍历所有内容,并将结果传递给方法findMatchingClassRoomIfAvailable(嗯,想必-您的示例不是很好)。如果您想为流中的每个项目记录一些内容,则只需将其记录在该方法的顶部即可。

滥用吗?我不这么认为。我会这样写吗?不。