2016-09-17 9 views
3

通常、GroovyのinjectメソッドはJava 8のreduceと同等であると思いますが、私は珍しい状況に遭ったようです。私は本のコレクションを持っているとキーがIDSで、値がブックされているマップに変換したい場合は同様のJava 8を使用しないGroovyのインジェクト

私はPOJO(またはPOGO)を持っていると言うが、Book

class Book { 
    int id 
    String name 
} 

と呼ばれますその後、Groovyでそれを書くのは簡単です:

Map bookMap = books.inject([:]) { map, b -> 
    map[b.id] = b 
    map 
} 

すなわち、各書籍のために、本書のIDでマップに追加し、マップを返します。

Java 8では、同じ操作では全く異なるアプローチがとられます。この次のいずれかの

Map<Integer, Book> bookMap = books.stream() 
      .collect(Collectors.toMap(Book::getId, b -> b)); 

または、同等に、

bookMap = books.stream() 
      .collect(Collectors.toMap(Book::getId, Function.identity())); 

違いはスタイルの問題であること。

ただし、Java 8にreduce操作があり、Groovyのinjectに似ていると私は思っています。

T reduce(T identity, BinaryOperator<T> accumulator) 

BinaryOperator

は、ラムダ式の両方の要素が同じ型でなければならないことを意味します。Java 8で reduceの署名があるので、私はちょうど、私がGroovyで何をしたか模倣することはできません。 BiFunctionだった場合、ラムダの最初の引数は HashMap<Integer, Book>に、2番目の引数は Bookにすることができましたが、 BinaryOperatorで行うことはできません。私は reduceの3つの引数のバージョンがあることを知っていますが、それはどちらかを助けるようには思われません。

明らかなものがありませんか?それはちょうどinjectより一般的ですそれはreduceですか?私はすでにJavaで問題を解決する慣用的な方法を持っているので、これは重要ではありませんが、私はここでの違いに驚いています。

答えて

3

ヨーケン!

List<Book> books = Arrays.asList(
     new Book(1, "Book One"), 
     new Book(2, "Tim's memoirs"), 
     new Book(3, "Harry Potter and the sarcastic cat") 
); 

あなたが行うことができます:

Map<Integer, Book> reduce = books.stream().reduce(
     new HashMap<Integer, Book>(), 
     (map, value) -> { 
      map.put(value.id, value); 
      return map; 
     }, 
     (a, b) -> { 
      a.putAll(b); 
      return a; 
     } 
); 

を与えるために:

{ 
    1=Book{id=1, name='Book One'}, 
    2=Book{id=2, name='Tim's memoirs'}, 
    3=Book{id=3, name='Harry Potter and the sarcastic cat'} 
} 

を最初のパラメータがするものですあなたがそう考えると、3 parameter form of reduceが必要:-D

集める:

 new HashMap<Integer, Book>(), 

第2のパラメータは、現在のアキュムレータをとりBiFunction、およびストリーム内の次の要素であり、何らかの方法でそれらを組み合わせ:

その減らす呼における第三のバイナリ演算子:

 (a, b) -> { 
      a.putAll(b); 
      return a; 
     } 

は...あなたは、並列ストリームを実行していると仮定すると戻って一緒にすべての結果のマップを結合する方法

putputAllですvoidを返すことは醜い混乱になります:-(しかし、私は連鎖が90年代後半に人気のあるものではなかったと思います...

+0

これは私が必要としていたものです。私はまだreduceメソッドが(別のアキュムレータとコンバイナを使って)そのように設計されているのに対して、Groovyでの注入(これはいつものように)ははるかに簡単なのですが、やはり難しいです。 また、私は、 "HPと卑劣な猫"の皮肉な猫はおそらく、モルフォナガルであると思います。 – kousen

+0

コンバイナは 'parallel()'ストリームの場合にのみ使用されます。コンビネータに 'RuntimeException(" boom ")をスローすると、通常のストリームに対しては呼び出されません。 .. –

関連する問題