2016-03-22 44 views
4

我想对对象集合myClass进行流式处理,以便使用Collectors.groupingBy()对其进行分组。但是,我不想检索Map<String, List<myClass>>,而是将其按照对象myOutput分组,并检索Map<String, myOutput>。我试图创建一个自定义的收藏家:Java 8通过对象上的收集器进行分组

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) 

我知道在这种情况下a减少会更容易,但我们假设在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值进行分组,并且对于每个元素分组到相同的a,您希望总计它们的b值。您可以使用内置的Collectors.summingInt(mapper),其中映射器返回值b

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

谢谢。我非常接近:(肯定内置的summingInt收集器在这种情况下会是一个更好的选择,但我想用一个可以理解的例子来描述我的问题。我的需求需要更多的复合体myClass和myOutput对象。 –