当前位置: 首页 > 面试题库 >

Java 8中的reduce累加器是否可以修改其参数?

拓拔飞飙
2023-03-14
问题内容

在Java 8中,Stream有一种减少方法

T reduce(T identity, BinaryOperator<T> accumulator);

是否允许累加器运算符修改其两个参数之一?我猜不是因为JavaDoc说累加器应该是NonInterfering,尽管所有示例都提到修改集合,而不是修改集合的元素。

因此,举一个具体的例子,如果我们有

 integers.reduce(0, Integer::sum);

并假设暂时Integer是可变的,是否sum可以通过向其添加第二个参数的值来修改其第一个参数?

我猜不是,但是我也想举个例子说明这种干扰会引起什么问题。


问题答案:

否。累加器不应修改其自变量。它接受两个值并产生一个新值。如果要在累积过程中使用突变(例如,将字符串累积到StringBuffer中而不是进行串联),请使用Stream.collect()专为此目的而设计的。

这是一个代码示例,如果您尝试这样做会产生错误的答案。假设您要对假设的MutableInteger类进行加法:

// Don't do this
MutableInteger result = stream.reduce(new MutableInteger(0), (a,b) -> a.add(b.get()));

得出错误答案的原因之一是,如果我们并行拆分计算,则现在两个计算共享相同的可变起始值。注意:

a + b + c + d
= 0 + a + b + 0 + c + d  // 0 denotes identity
= (0 + a + b) + (0 + c + d) // associativity

因此我们可以自由拆分流,计算和的0 + a + b0 + c + d,然后将结果相加。但是,如果它们共享相同的标识值,并且由于其中一项计算而导致该值发生了变异,则其他计算可能会从错误的值开始。

(还要注意,如果实现值得,即使对于顺序计算,也可以允许该实现执行此操作。)



 类似资料:
  • 在Java 8中,Stream有一个方法reduce: 累加器运算符是否允许修改其任一参数?我不这么认为,因为JavaDoc说累加器应该是非干涉的,尽管所有示例都谈到修改集合,而不是修改集合的元素。 举个具体的例子,如果我们有 假设整数是可变的,那么可以通过将第二个参数的值添加到第一个参数中(就地)来修改第一个参数吗? 我想不会,但我也想举一个例子,说明这种干扰在哪里会引起问题。

  • 问题内容: 是否可以逐行解析文件,并在逐行浏览时就地编辑行? 问题答案: 可以像·的·模块一样使用备份文件来模拟它。 这是一个示例脚本,该脚本·从命令行或上给出的文件中删除不满意的行stdin: 例: 完成后·,·文件将仅包含满足·谓词的行。

  • 问题内容: TensorFlow图通常从输入到输出逐渐构建,然后执行。查看Python代码,操作的输入列表是不可变的,这表明不应修改输入。这是否意味着无法更新/修改现有图形? 问题答案: TensorFlow类是 仅追加的 数据结构,这意味着您可以在执行图的一部分后将节点添加到图,但不能删除或修改现有节点。由于TensorFlow在您调用时仅执行必要的子图,因此图中没有冗余节点(尽管它们将继续消耗

  • 问题内容: 在Python中,是否可以在运行时重新定义函数的默认参数? 我在这里定义了带有3个参数的函数: 接下来,我尝试(未成功)设置y的默认参数值,然后尝试调用不带参数的函数: 但是由于未正确设置默认值,所以产生了以下错误: 正如我在此尝试的那样,是否可以在运行时重新定义函数的默认参数? 问题答案: 只需使用functools.partial 这里的一个问题:您将无法调用它,因为您应该手动说

  • 问题内容: 我想在过滤器/ servlet中拦截请求,并向其中添加一些参数。但是,该请求不会公开’setParameter’方法,并且该参数映射在被操纵时会抛出错误,表明已被锁定。有没有其他我可以尝试的方法? 问题答案: 子类化并覆盖方法。该类的描述为: 提供HttpServletRequest接口的便捷实现,希望希望使请求适应Servlet的开发人员可以将其子类化。 在过滤器中,将请求包装在子类

  • 问题内容: 是否可以通过修改beforeSend回调中的XMLHttpRequest对象来修改Ajax请求中发送的数据?如果可以,我该怎么做? 问题答案: 是的,您可以对其进行修改, 实际上是的签名(在jQuery 1.4+中): __ 即使文档只是just ,您也可以在这里看到它的名称,settings对象在哪里: 因此,您 可以 在此之前修改参数(请注意 __ ,即使传入了一个对象, 到目前为