2016-10-12 8 views
3

従来の関数型言語では、初期値とアキュムレータの値をリストの中で減らすことを考えています。 JavaではBinaryOperatorが必要なため、操作が複雑になります。BiFunctionのみを減らす

私たちはこのような機能を書くのより良い方法を持っているかどうかを知りたい:

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とは違う何かを使うべきですか?

+1

何をしますか?この 'BinaryOperator'引数が何であるのか、そしてなぜそれがあるのか​​を知っていますか(これについてはこちらをご覧くださいhttp://stackoverflow.com/questions/22808485/purpose-of-third-argument-to-reduce-function-in-java-8-関数型プログラミング)? – Tunaki

+3

引数を変更している場合は、 'reduce'ではなく' collect'を使用してください。これは意図したようにも機能しないので、あなたのタスクはストリーム操作にはまったく適していません。 – Holger

+0

@ Tunaki私は、clojure、lisp、scheme、haskell、smalltalk、... foldl/foldrと同じように、BinaryOperatorは1つの型 'U acc(U、U)'のみを受け入れるので、reduceではありません。適切な削減関数は 'U acc(U、T)'です。 – mathk

答えて

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; 
} 
関連する問題