我的程序有这一行:
Function<String, Integer> f = (String s) -> s.chars().reduce(0, (a, b) -> 2 * a + b);
传递给reduce的函数不是关联的。 Reduce的文档说传递的函数必须是关联的。
如何将此重写为不会破坏合同的表达式?
答案 0 :(得分:4)
在当前的实现和 IFF下,您不会使用并行 - 您现在拥有的是安全的。显然,如果你对这些免责声明没问题。
或者您可以使用for循环显然创建函数:
Function<String, Integer> f = s -> {
int first = s.charAt(0) * 2 + s.charAt(1);
int total = first;
for (int x = 1; x < s.length() - 1; x++) {
total = total * 2 + s.charAt(x + 1);
}
return total;
};
答案 1 :(得分:3)
您可以将此功能转换为关联功能,如List.hashCode()
中2
示例中所述。不同之处仅在于因素(31
vs。1
)和起始值(0
vs。String
)。
它可以适应您的任务,当您拥有Function<String, Integer> f =
s -> IntStream.range(0, s.length()).map(i -> s.charAt(i)<<(s.length()-i-1)).sum();
之类的随机访问输入时,这一点尤为简单:
for
这甚至可以并行运行,但是你不可能遇到如此庞大的字符串,并行评估会带来好处。那么剩下的是,大多数人可能会认为这个解决方案比简单的String
循环更难阅读......
请注意,上述解决方案表现出不同的溢出行为,即如果char
超过32 Function<String, Integer> f = s ->
IntStream.range(Math.max(0, s.length()-32), s.length())
.map(i -> s.charAt(i)<<(s.length()-i-1)).sum();
s,则由于使用了移位运算符而不是乘以2。
解决此问题的方法使解决方案更加高效:
char
如果字符串超过32 char
s,它只处理最后32 {{1}} s,这已足以计算与原始函数相同的结果。