我看到一张rule in Sonar,上面写着:

与其他中间流操作的一个关键区别是,流实现可以出于优化目的自由地跳过对peek()的调用.这可能会导致仅针对Stream中的某些元素意外调用peek(),或者不调用任何元素.

此外,Javadoc中也提到了这一点,上面写道:

此方法主要用于支持调试,您希望在元素流过管道中的某个点时查看元素

在什么情况下可以跳过java.util.Stream.peek()?是不是跟调试有关?

推荐答案

不仅peek可以跳过,map也可以跳过.这是为了优化. 例如,当调用终端操作count()时,由于这样的操作不改变当前项的数量/计数,所以对于peekmap而言,各个项没有意义.

这里有两个例子:


1.Map和PEEK are not skipped,因为过滤器可以预先更改项目数.

long count = Stream.of("a", "aa")
    .peek(s -> System.out.println("#1"))
    .filter(s -> s.length() < 2)
    .peek(s -> System.out.println("#2"))
    .map(String::length)
    .count();
#1
#2
#1
1

2.Map和PEEK are skipped,因为条目的数量没有变化.

long count = Stream.of("a", "aa")
    .peek(s -> System.out.println("#1"))
    //.filter(s -> s.length() < 2)
    .peek(s -> System.out.println("#2"))
    .map(String::length)
    .count();
2

Important:这些方法不应该有side-effects.

一般来说,流操作的行为参数的副作用是不受鼓励的,因为它们通常会导致无意中违反无状态要求,以及其他线程安全风险.

以下实现是危险的.假设callRestApi方法执行REST调用,则不会执行该调用,因为Stream违反了副作用.

long count = Stream.of("url1", "url2")
                .map(string -> callRestApi(HttpMethod.POST, string))
                .count();
/**
 * Performs a REST call
 */
public String callRestApi(HttpMethod httpMethod, String url);

Java相关问答推荐

Java Streams在矩阵遍历中的性能影响

OpenJDK、4K显示和文本质量

如何在返回bigint []值的子查询中使用any?

如何判断一个矩阵是否为有框矩阵?

我无法获取我的Java Spring应用程序的Logback跟踪日志(log)输出

试着做一个2x2的魔方求解算法,我如何找到解路径(DFS)?

try 判断可选参数是否为空时出现空类型安全警告

SpringBoot Kafka自动配置-适用于SASL_PLAYTEXT的SSLBundle 包,带SCRAM-SHA-512

如何将其他属性引用到log4j2 yaml配置中?

匹配一组字符或另一组字符

虚拟线程应该很快消亡吗?

是否在settings.xml中使用条件Maven镜像?

try 使用预准备语句占位符获取信息时出现Try-With-Resources错误

JavaFX:无论何时显示应用程序,如何更改组件/ node 位置?

获取所有可以处理Invent.ACTION_MEDIA_BUTTON Android 13 API33的Android包

SonarQube在合并升级到java17后对旧代码提出错误

如何在java中从以百分比表示的经过时间和结束日期中找到开始日期

具有 DayOfWeek 列表的 JPA 实体

在 Java Spring Boot 中注入而不是实例化抽象类

当一个 boolean 或 int 被放置在包含对象的 java Map 中时,放置它们实际上会创建一个新对象吗?