Java API 文档指出 combiner collect 的参数方法必须是:
an associative, non-interfering, stateless function for combining two values, which must be compatible with the accumulator function
A combiner是 BiConsumer<R,R>接收两个 R 类型的参数并返回 void .但是文档没有说明我们是否应该将元素组合到第一个或第二个参数中?
例如,以下示例可能会给出不同的结果,具体取决于组合顺序:m1.addAll(m2)或 m2.addAll(m1) .
List<String> res = LongStream
.rangeClosed(1, 1_000_000)
.parallel()
.mapToObj(n -> "" + n)
.collect(ArrayList::new, ArrayList::add,(m1, m2) -> m1.addAll(m2));
我知道在这种情况下我们可以简单地使用方法句柄,例如 ArrayList::addAll .然而,在某些情况下需要 Lambda,我们必须以正确的顺序组合这些项目,否则在并行处理时我们可能会得到不一致的结果。
Java 8 API 文档的任何部分是否声明了这一点?还是真的没关系?
最佳答案
当然,这很重要,因为当您使用 m2.addAll(m1) 时而不是 m1.addAll(m2) ,它不仅改变了元素的顺序,而且完全破坏了操作。自BiConsumer不返回结果,您无法控制调用者将使用哪个对象作为结果,并且由于调用者将使用第一个对象,修改第二个对象将导致数据丢失。
如果您查看类型为 BiConsumer<R,? super T> 的accumulator 函数,就会有一个提示。 ,换句话说,除了存储类型为 T 的元素外,不能做任何事情。 ,作为第二个参数提供,放入 R 类型的容器中, 作为第一个参数提供。
如果您查看 documentation of Collector ,它使用 BinaryOperator作为 combiner 函数,因此允许 combiner 决定返回哪个参数(甚至是完全不同的结果实例),您会发现:
The associativity constraint says that splitting the computation must produce an equivalent result. That is, for any input elements
t1andt2, the resultsr1andr2in the computation below must be equivalent:A a1 = supplier.get(); accumulator.accept(a1, t1); accumulator.accept(a1, t2); R r1 = finisher.apply(a1); // result without splitting A a2 = supplier.get(); accumulator.accept(a2, t1); A a3 = supplier.get(); accumulator.accept(a3, t2); R r2 = finisher.apply(combiner.apply(a2, a3)); // result with splitting
因此,如果我们假设 accumulator 是按遇到顺序应用的,则 combiner 必须按从左到右的顺序组合第一个和第二个参数以产生一个等效结果。
现在,Stream.collect 的三参数版本签名略有不同,使用 BiConsumer作为组合器 exactly for supporting method references like ArrayList::addAll .假设所有这些操作的一致性并考虑此签名更改的目的,我们可以安全地假设它必须是要修改的容器的第一个参数。
但似乎这是一个较晚的更改,文档没有相应地调整。如果您查看 Mutable reduction包文档的一部分,您会发现它已经过调整以显示实际的 Stream.collect的签名和用法示例,但重复了与上面所示的关联约束完全相同的定义,尽管 finisher.apply(combiner.apply(a2, a3))如果 combiner 则不起作用是 BiConsumer ……
文档问题已报告为 JDK-8164691并在 Java 9 中解决。The new documentation说:
combiner - an associative, non-interfering, stateless function that accepts two partial result containers and merges them, which must be compatible with the accumulator function. The combiner function must fold the elements from the second result container into the first result container.
关于java - collect(supplier, accumulator, combiner)的组合器的组合顺序在哪里定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30526324/
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是