传递非关联函数以减少

时间:2017-11-13 17:23:21

标签: java java-8 java-stream

我的程序有这一行:

Function<String, Integer> f = (String s) -> s.chars().reduce(0, (a, b) -> 2 * a + b);

传递给reduce的函数不是关联的。 Reduce的文档说传递的函数必须是关联的。

如何将此重写为不会破坏合同的表达式?

2 个答案:

答案 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,这已足以计算与原始函数相同的结果。