Во-первых, функции объединения не нужно вызывать, если вы не используете несколько потоков (параллельный поток).Комбайнер вызывается для объединения результатов операции над фрагментами вашего потока.Здесь нет параллелизма, поэтому не нужно вызывать сумматор.
Вы получаете нулевые значения из-за функции накопителя.Выражение
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
, позвоните accumulate
в функции accumulator
и т. Д.
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}