【问题标题】:Reduce with BiFunction only仅使用 BiFunction 减少
【发布时间】:2016-10-12 10:28:54
【问题描述】:

传统的函数式语言在列表上考虑初始值和累加器的减少。在 Java 中,事情更复杂,因为它需要 BinaryOperator。

我想知道我们是否有更好的方法来编写这种函数:

public JsonObject growPath(final JsonObject obj) {
    // paths is a list of string
    return this.paths.stream().reduce(obj, (child, path) -> {
        if (!child.containsKey(path) || !(child.get(path) instanceof JsonObject)) {
            // We do override anything that is not an object since the path
            // specify that it should be an object.
            child.put(path, JsonObject.create());
        }
        return child.getObject(path);
    } , (first, last) -> {
        return last;
    });
}

我想避免使用 BinaryOperator 参数。我应该使用与 reduce 不同的东西吗?

【问题讨论】:

  • 你想做什么?你知道这个BinaryOperator 参数的用途以及它为什么存在(参见这个stackoverflow.com/questions/22808485/…)吗?
  • 如果要修改参数,则不应使用reduce,而应使用collect。由于这也不会像您预期的那样工作,因此您的任务根本不适合 Stream 操作。
  • @Tunaki 我想要与 clojure、lisp、scheme、haskell、smalltalk、... aka foldl/foldr 中相同的 reduce,BinaryOperator 不是减少,因为它只接受一种类型 U acc(U,U)。一个合适的归约函数是U acc(U,T)
  • @mathk 是的,看看链接的问题,这个参数用于并行计算。也可以看看stackoverflow.com/questions/25880331/…reduce 很可能不是您想要的。
  • @Tunaki 实际上,我什至没有考虑并行计算。如果可以将其用于并行计算,那很好,但这不是我想要的。我只是在寻找一种更实用的处理列表的方式。我虽然该流可能是实现这一目标的方法,但看起来并非如此。

标签: java-8 reduce


【解决方案1】:

您为这项工作使用了错误的工具。您正在执行修改obj 的操作,这与减少完全无关。如果我们忽略修改方面,则此操作是左折叠,Streams 不支持(通常)。如果函数是关联的,您只能使用reduce 来实现它,而您的函数不是。所以你最好在没有 Streams 的情况下实现它:

public JsonObject growPath(JsonObject obj) {
    for(String path: this.paths)
        obj = (JsonObject)obj.compute(path,
            (key,child)->child instanceof JsonObject? child: JsonObject.create());
    return obj;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 2012-01-05
    • 2014-05-01
    相关资源
    最近更新 更多