Java 8 GroupingBy与对象上的收集器

Ant*_*let 5 java java-8 java-stream collectors

我想流式传输一个对象集合,myClass以便使用它进行分组Collectors.groupingBy().但是,Map<String, List<myClass>>我想将它分组在一个对象上myOutput并检索一个,而不是检索一个Map<String, myOutput>.我试图创建一个自定义收集器:

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)));
Run Code Online (Sandbox Code Playgroud)

我的课 :

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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

但是使用此代码,收集器存在问题:

Collectors.of(myOutput::new, myOutput::accept, myOutput::combine)
Run Code Online (Sandbox Code Playgroud)

我知道在这种情况下减少会更容易,但我们假设在myOutput对象中有很多操作要做.

这个收藏家怎么了?

Tun*_*aki 6

你的收藏家很好.你只需要拥有Collector.of静态工厂(而不是Collectors.of).

这编译很好,并具有您想要的输出

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

但请注意,您不需要这样的收集器.您可以重复使用现有的.在这种情况下,您希望按a值分组,并且对于分组为相同的每个元素a,您希望对它们的b值求和.您可以使用Collectors.summingInt(mapper)mapper返回b值的内置函数:

Map<String,Integer> myMap = 
    myList.stream()
          .collect(Collectors.groupingBy(
            myClass::getA, 
            Collectors.summingInt(myClass::getB)
          ));
Run Code Online (Sandbox Code Playgroud)