Как имплементировать метод characteristics() при реализации класса Collector?
Пытаюсь реализовать Collector (Java 8, Stream API), создавая объект анонимного класса. Я застрял на имплементации метода characteristics().
Вот, что о нём написано в javadoc:
Returns a Set of Collector.Characteristics indicating the characteristics of this Collector. This set should be immutable.
Проблема в том, что всего в Characteristics есть три варианта того, что можно возвращать: IDENTITY_FINISH, UNORDERED, IDENTITY_FINISH. Но ни одно из этих свойств мне не нужно.
Сейчас я реализовал Collector вот так (самое важно внизу):
Collector<UserMeal, List<UserMealWithExcess>, List<UserMealWithExcess>> mealsCollector =
new Collector<UserMeal, List<UserMealWithExcess>, List<UserMealWithExcess>>() {
private Map<LocalDate, Integer> dateExcess = new HashMap<>();
@Override
public Supplier<List<UserMealWithExcess>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<UserMealWithExcess>, UserMeal> accumulator() {
return (o, o2) -> {
o.add(new UserMealWithExcess(o2.getDateTime(), o2.getDescription(), o2.getCalories(), new Boolean[]{false}));
dateExcess.merge(LocalDate.from(o2.getDateTime()), o2.getCalories(), Integer::sum);
};
}
@Override
public BinaryOperator<List<UserMealWithExcess>> combiner() {
return (o, o2) -> {
o.addAll(o2);
return o;
};
}
@Override
public Function<List<UserMealWithExcess>, List<UserMealWithExcess>> finisher() {
return (o) -> {
o.forEach(x -> x.getExcess()[0] = (dateExcess.get(LocalDate.from(x.getDateTime())) > caloriesPerDay));
return o;
};
}
@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED));
}
};
Насколько видно, сейчас characteristics() возвращает Characteristics.UNORDERED, т.е. этот маркер сообщает о том, что коллекция неупорядочена.
А можно мне вообще ничего не возвращать в этом методе? Есть ли какое-то дефолное свойство?
Потому что, если возвращать null, это вызовет NullPointerException.
Ответы (1 шт):
Ответом на вопрос является return Collections.emptySet();, но может кому-то будет интересно, что это и с чем его едят.
Дело в том, что метод characteristics() подсказывает приложению как обращаться с элементами при терминальной операции.
Возвращаемый Set<Characteristics> содержит дополнительную информацию для оптимизации. По большей части она нужна в многопоточных реализациях.
Collector.Characteristics.IDENTITY_FINISH- Означает, что в терминальной операции будет возвращён единственный элемент, так что аккумулятор можно сразу скастовать к необходимому типу ((R) finalAccum). В противном случае вызывается дополнительные методыcollector.finisher().apply(finalAccum).Collector.Characteristics.UNORDERED- элементы имеют ассоциативность (a*(b*c)==b*(a*c)), но при этом может отсутствовать коммутативность (a*bне всегда равноb*a). В документации приводится пример комбинации двух списковList, для них ослаблена операция эквивалентности, предоплагается, что если эти два списка содержат одинаковый набор одинаковых элементов, то они равны, не смотря на то, что сами одинаковые элементы могут находятся в разных позициях этих списков.При исполнении этого кода
A a2 = supplier.get(); accumulator.accept(a2, t1); A a3 = supplier.get(); accumulator.accept(a3, t2); R r2 = finisher.apply(combiner.apply(a2, a3));На последней строке сохраняется порядок комбинации коллекций
combiner.apply(a2, a3), что требует сохранения порядка выполнения операций.Collector.Characteristics.CONCURRENT- Аккумуляторы могут быть одновременно вызваны в нескольких потоках, при этом если коллектор не содержит характеристикиCollector.Characteristics.UNORDERED, то многопоточная реализация может быть применена только к неупорядоченным (unnordered) коллекциям, например кSet.
Более подробная информация по коллекторам.