2016-03-22 5 views
4

Collectors.groupingBy()を使用してオブジェクトをグループ化するためにオブジェクトmyClassのコレクションをストリーミングしたいとします。しかし、Map<String, List<myClass>>を取得する代わりに、オブジェクトmyOutputにグループ化してMap<String, myOutput>を取得したいと考えています。私は、カスタムコレクタを作成しようとしました:オブジェクトにコレクタを持つJava 8 GroupingBy

List<myClass> myList = new ArrayList<myClass>(); 
myList.add(new myClass("a", 1)); 
myList.add(new myClass("a", 2)); 
myList.add(new myClass("b", 3)); 
myList.add(new myClass("b", 4)); 

Map<String,myOutput> myMap = myList.stream().collect(Collectors.groupingBy(myClass::getA, Collectors.of(myOutput::new, myOutput::accept, myOutput::combine))); 

MYCLASS:

protected String a; 
protected int b; 

public myClass(String aA, int aB) 
{ 
    a = aA; 
    b = aB; 
} 

public String getA() 
{ 
    return a; 
} 

public int getB() 
{ 
    return b; 
} 

がmyOutput:

protected int i; 

public myOutput() 
{ 
    i = 0; 
} 

public void accept(myClass aMyClass) 
{ 
    i += aMyClass.getB(); 
} 

public myOutput combine(myOutput aMyOutput) 
{ 
    i += aMyOutput.getI(); 
    return this; 
} 

public int getI() 
{ 
    return i; 
} 

しかし、このコードで、コレクターに問題がある:

Collectors.of(myOutput::new, myOutput::accept, myOutput::combine) 

この場合、私は知っていますreduceははるかに簡単ですが、myOutputオブジェクトで行う操作が多いとしましょう。

このコレクターに問題がありますか?

答えて

6

コレクターは問題ありません。 Collector.ofの静的な工場が必要です(Collectors.ofではなく)。

これは罰金コンパイルし、出力を持っているあなたは、あなたが、このようなコレクタを必要としないこと、しかし、

Map<String,myOutput> myMap = 
     myList.stream() 
       .collect(Collectors.groupingBy(
       myClass::getA, 
       Collector.of(myOutput::new, myOutput::accept, myOutput::combine) 
      )); 

注意をしたいです。既存のものを再利用することができます。この場合、aの値でグループ化し、同じ要素にグループ化された各要素について、abの値を合計します。

Map<String,Integer> myMap = 
    myList.stream() 
      .collect(Collectors.groupingBy(
      myClass::getA, 
      Collectors.summingInt(myClass::getB) 
     )); 
+0

ありがとう:あなたは、組み込みのCollectors.summingInt(mapper)マッパーがb値を返す場所を使用することができます。私は非常に近いです:(組み込みのsummingIntコレクタがこのケースではより良い選択肢になることは確かですが、わかりやすい例で私の問題を説明したかったのですが、myClassとmyOutputオブジェクトはもっと複雑になりました。 –

関連する問題