gpt4 book ai didi

java - Collectors.groupingBy 的自定义收集器无法按预期工作

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:19:40 27 4
gpt4 key购买 nike

考虑简单类Foo:

public class Foo {

public Float v1;
public Float v2;
public String name;

public Foo(String name, Float v1, Float v2) {
this.name = name;
this.v1 = v1;
this.v2 = v2;
}

public String getName() {
return name;
}
}

现在,我有一个 Foo 集合,我想按 Foo::getName 对它们进行分组。我编写了一个自定义收集器来执行此操作,但它似乎没有按预期工作。更准确地说,combiner() 永远不会被调用。为什么?

public class Main {

public static void main(String[] args) {

List<Foo> foos = new ArrayList<>();
foos.add(new Foo("blue", 2f, 2f));
foos.add(new Foo("blue", 2f, 3f));
foos.add(new Foo("green", 3f, 4f));

Map<String, Float> fooGroups = foos.stream().collect(Collectors.groupingBy(Foo::getName, new FooCollector()));
System.out.println(fooGroups);
}

private static class FooCollector implements Collector<Foo, Float, Float> {

@Override
public Supplier<Float> supplier() {
return () -> new Float(0);
}

@Override
public BiConsumer<Float, Foo> accumulator() {
return (v, foo) -> v += foo.v1 * foo.v2;
}

@Override
public BinaryOperator<Float> combiner() {
return (v1, v2) -> v1 + v2;
}

@Override
public Function<Float, Float> finisher() {
return Function.identity();
}

@Override
public Set<Characteristics> characteristics() {
Set<Characteristics> characteristics = new TreeSet<>();
return characteristics;
}
}
}

最佳答案

首先,如果您不使用多线程(并行流),则不需要调用组合器函数。组合器被调用以组合对流的 block 的操作结果。这里没有并行性,因此不需要调用组合器。

由于累加器函数,您得到的值为零。表达式

v += foo.v1 * foo.v2;

替换 v 为新的 Float 对象。原始累加器对象没有被修改;它仍然是 0f。此外,Float 与其他数字包装类型(和 String)一样是不可变的,无法更改。

您需要一些其他类型的可变累加器对象。

class FloatAcc {
private Float total;
public FloatAcc(Float initial) {
total = initial;
}
public void accumulate(Float item) {
total += item;
}
public Float get() {
return total;
}
}

然后您可以修改您的自定义 Collector 以使用 FloatAcc。提供一个新的FloatAcc,在accumulator函数中调用accumulate,等等。

class FooCollector implements Collector<Foo, FloatAcc, Float> {
@Override
public Supplier<FloatAcc> supplier() {
return () -> new FloatAcc(0f);
}
@Override
public BiConsumer<FloatAcc, Foo> accumulator() {
return (v, foo) -> v.accumulate(foo.v1 * foo.v2);
}
@Override
public BinaryOperator<FloatAcc> combiner() {
return (v1, v2) -> {
v1.accumulate(v2.get());
return v1;
};
}
@Override
public Function<FloatAcc, Float> finisher() {
return FloatAcc::get;
}
@Override
public Set<Characteristics> characteristics() {
Set<Characteristics> characteristics = new TreeSet<>();
return characteristics;
}
}

通过这些更改,我得到了您所期望的:

{green=12.0, blue=10.0}

关于java - Collectors.groupingBy 的自定义收集器无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54656992/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com