Не судите строго, это мой первый моноид
Посмотреть код
public class Main {
public static void main(String[] args) {
var results = List.of(
new GameResult("Petr", 120),
new GameResult("Ivan", 350),
new GameResult("Ann", 210),
new GameResult("Marie", 290)
);
var best = Extension.fold(
results,
new Max<>(GameResult::new)
);
System.out.println(best);
}
}
interface Monoid<T> {
T zero();
T plus(T left, T right);
}
final class Extension {
public static <T> T fold(
Collection<T> collection,
Monoid<T> monoid
) {
return collection.stream()
.reduce(monoid.zero(), monoid::plus);
}
}
record GameResult(String player, int score) implements Comparable<GameResult> {
GameResult() {
this("", Integer.MIN_VALUE);
}
@Override
public int compareTo(GameResult o) {
return Integer.compare(score, o.score);
}
}
final class Max<T extends Comparable<T>> implements Monoid<T> {
private final Supplier<T> zeroSupplier;
public Max(Supplier<T> zeroSupplier) {
this.zeroSupplier = zeroSupplier;
}
@Override
public T zero() {
return zeroSupplier.get();
}
@Override
public T plus(T left, T right) {
return left.compareTo(right) > 0
? left
: right;
}
}
И не пишите, что можно было бы написать это в одну строчку!
var best = results.stream()
.max(Comparator.naturalOrder())
.orElse(null);
Моноид здесь, действительно, избыточен. Обычная функциональная цепочка для нахождения максимума читается и пишется намного проще.
Смысл приседания с моноидом в том, что мы универсально описываем, как объект должен вести себя в свёртке,
вместо того, чтобы фиксировать алгоритм непосредственно в reduce:
collection.stream()
.reduce(
// с чего начинаем / отсутствие результата
monoid.zero(),
// как объединить два результата
monoid::plus
);
// vs
results.stream()
.reduce(
// с чего начинаем / отсутствие результата
new GameResult(),
// как объединить два результата
(left, right) -> left.score() > right.score()
? left
: right
);
Всё ради переиспользуемости кода. Моноид можно поменять, а код внутри reduce останется без
изменений, он знает как с ним работать.
Познакомиться подробнее с темой можно здесь.
← Назад к списку статей