В этой статье рассматривается расширение Java Перечисление
s используется в качестве значений свойств в JavaBeans в сочетании с Java Stream API для создания и расширения fluent интерфейсов . Из Википедия :
В программной инженерии – свободный интерфейс … это метод разработки объектно-ориентированных API-интерфейсов, основанный в значительной степени на цепочке методов с целью сделать читаемость исходного кода близкой к читаемости обычной письменной прозы, по существу создавая специфичный для предметной области язык в интерфейсе.
Java Stream API предоставляет цепочку методов; в этой статье будет рассмотрено, как Java Enum
s может быть расширен (специально для реализации Предикат
чтобы способствовать тому, чтобы плавный интерфейс был похож на “письменную прозу”. ” Например:
public enum Rank implements Predicate{ JOKER, ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING; ... } public enum Suit implements Predicate { CLUBS, DIAMONDS, HEARTS, SPADES; ... } public class Card { private final Suit suit; private final Rank rank; ... }
позволит поддерживать плавные выражения, такие как:
Listhand = ...; boolean areAllHearts = hand.stream() .filter(Suit.HEARTS) .allMatch(); boolean hasKingOfSpades = hand.stream() .filter(Rank.KING.and(Suit.SPADES)) .anyMatch();
Предоставляется полный javadoc .
Расширяющиеся перечисления
Значения Enum
являются константами, но они также являются подклассами Enum
, и реализации этих подклассов могут иметь пользовательские поля и методы. Например, java.time. День недели
реализует Временный доступ
и Временная регулировка TemporalAdjuster
интерфейсы so DayOfWeek
предоставляет методы реализации для этих методов интерфейса. TemporalAdjuster интерфейсы so
DayOfWeek
public enum Suit { CLUBS(Color.BLACK, "\u2667"), DIAMONDS(Color.RED, "\u2662"), HEARTS(Color.RED, "\u2661"), SPADES(Color.BLACK, "\u2664"); ... private final Color color; private final String string; @ConstructorProperties({ "color", EMPTY }) private Suit(Color color, String string) { this.color = color; this.string = string; } public Color getColor() { return color; } @Override public String toString() { return string; } ... }
TemporalAdjuster || интерфейсы so || DayOfWeek || предоставляет методы реализации для этих методов интерфейса. Реализация || Suit || демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора.
TemporalAdjuster интерфейсы so
DayOfWeek предоставляет методы реализации для этих методов интерфейса. Реализация
Suit демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
Stream , является то, что подкласс
Enum реализует
Predicate . TemporalAdjuster
интерфейсы so DayOfWeek
предоставляет методы реализации для этих методов интерфейса. Реализация Suit
демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
public enum Rank implements Predicate{ ... @Override public boolean test(Card card) { return is(this).test(card.getRank()); } ... public static Predicate is(Rank rank) { return t -> Objects.equals(rank, t); } ... } public enum Suit implements Predicate { ... @Override public boolean test(Card card) { return is(this).test(card.getSuit()); } ... public static Predicate is(Suit rank) { return t -> Objects.equals(rank, t); } ... }
TemporalAdjuster интерфейсы so
DayOfWeek
TemporalAdjuster интерфейсы so
DayOfWeek предоставляет методы реализации для этих методов интерфейса. Реализация
Suit демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
Stream , является предикат
, который должен протестировать компонент, который затем , Конечно,
fRank и
Suit
TemporalAdjuster || интерфейсы so || DayOfWeek || предоставляет методы реализации для этих методов интерфейса. Реализация || Suit || демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого || Stream ||, является то, что предикат || должен протестировать компонент, который затем ||, Конечно, || fRank || и || Suit || должны протестировать || Card ||: например, || Enum || – это примечание: Обе реализации предоставляют статические || is || методы для Furtrank || и || Suit || являются свойствами компонента || Card || Для повторной реализации – Рейтинг покерных рук Rank || и || Suit || реализованы как внутренние классы || Card || . тот факт, что || her способствует “беглости” API. собственность для. или подкласс || Enum || для реализации || Предиката || .
TemporalAdjuster интерфейсы so
DayOfWeek предоставляет методы реализации для этих методов интерфейса. Реализация
Suit
public enum Ranking implements Predicate> { Empty(0, Collection::isEmpty), HighCard(1, t -> true), Pair(2, Rank.SAME), TwoPair(4, Pair.with(Pair)), ThreeOfAKind(3, Rank.SAME), Straight(5, Rank.SEQUENCE), Flush(5, Suit.SAME), FullHouse(5, ThreeOfAKind.with(Pair)), FourOfAKind(4, Rank.SAME), StraightFlush(5, holding(ACE, KING).negate().and(Straight).and(Flush)), RoyalFlush(5, holding(ACE, KING).and(Straight).and(Flush)), FiveOfAKind(5, Rank.SAME); private final int required; private final Predicate
> is; private Ranking(int required, Predicate
> is) { this.required = required; this.is = Objects.requireNonNull(is); } ... public int required() { return required; } ... @Override public boolean test(List
list) { return (list.size() >= required() && is.test(subListTo(list, required()))); } ... }
TemporalAdjuster интерфейсы so
DayOfWeek предоставляет методы реализации для этих методов интерфейса. Реализация
Suit демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
Stream , является предикат
, который должен протестировать компонент, который затем
... private staticPredicate > same(Function
> mapper) { return t -> ((! t.isEmpty()) && t.stream().allMatch(mapper.apply(t.get(0)))); } ... public enum Rank implements Predicate { ... public static final Predicate > SAME = same(Card::getRank); ... } ... public enum Suit implements Predicate
{ ... public static final Predicate > SAME = same(Card::getSuit); ... } ...
TemporalAdjuster
интерфейсы so DayOfWeek
предоставляет методы реализации для этих методов интерфейса. Реализация Suit
демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
... private staticList listOf(Collection collection, Function mapper) { return collection.stream().map(mapper).collect(Collectors.toList()); } ... public enum Rank implements Predicate { ... public static final List ACE_HIGH = unmodifiableList(asList(JOKER, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE)); public static final List ACE_LOW = unmodifiableList(asList(values())); private static final Map MAP; private static final List > SEQUENCES; static { TreeMap
map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); for (Rank rank : values()) { map.put(rank.name(), rank); map.put(rank.toString(), rank); } MAP = unmodifiableMap(map); List high = new ArrayList<>(Rank.ACE_HIGH); List low = new ArrayList<>(Rank.ACE_LOW); reverse(high); reverse(low); SEQUENCES = unmodifiableList(asList(unmodifiableList(high), unmodifiableList(low))); } ... public static final Predicate > SEQUENCE = t -> ((! t.isEmpty()) && sequence(listOf(t, Card::getRank))); private static boolean sequence(List
list) { return (SEQUENCES.stream().anyMatch(t -> indexOfSubList(t, list) >= 0)); } ... } ...
TemporalAdjuster интерфейсы so
DayOfWeek предоставляет методы реализации для этих методов интерфейса. Реализация
Suit демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
Stream
public enum Ranking implements Predicate> { ... private Predicate
> with(Predicate
> that) { return t -> test(t) && that.test(subListFrom(t, required())); } private static
Predicate > holding(int count, Predicate
> predicate) { return t -> (t.isEmpty() || predicate.test(subListTo(t, count))); } @SafeVarargs @SuppressWarnings({ "varargs" }) private static
Predicate > holding(Predicate
... array) { return holding(Stream.of(array).collect(Collectors.toList())); } private static Predicate > holding(List
> list) { return t -> ((list.isEmpty() || t.isEmpty()) || (list.get(0).test(t.get(0)) && (holding(subListFrom(list, 1)).test(subListFrom(t, 1))))); } private staticList subListTo(List list, int to) { return list.subList(0, Math.min(to, list.size())); } private static List subListFrom(List list, int from) { return list.subList(from, list.size()); } ... }
TemporalAdjuster интерфейсы so
DayOfWeek предоставляет методы реализации для этих методов интерфейса. Реализация
Suit демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
Stream , является то, что предикат
должен протестировать компонент, который затем , Конечно,
fRank и Suit
Listhand = ...; int size = Math.min(5, hand.size()); boolean isStraight = Combinations.of(size, hand) .filter(Ranking.STRAIGHT) .anyMatch();
TemporalAdjuster интерфейсы so
DayOfWeek предоставляет методы реализации для этих методов интерфейса. Реализация
Suit демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
Stream , является предикат
, который должен протестировать компонент, который затем , Конечно,
fRank и
Suit должны протестировать
Card : например,
Enum - это примечание: Обе реализации предоставляют статические
is
public enum Ranking implements Predicate> { Empty(0, null, Collection::isEmpty), HighCard(1, t -> true, t -> true), Pair(2, Rank.SAME, Rank.SAME), TwoPair(4, holding(2, Rank.SAME), Pair.with(Pair)), ThreeOfAKind(3, Rank.SAME, Rank.SAME), Straight(5, Rank.SEQUENCE, Rank.SEQUENCE), Flush(5, Suit.SAME, Suit.SAME), FullHouse(5, holding(3, Rank.SAME), ThreeOfAKind.with(Pair)), FourOfAKind(4, Rank.SAME, Rank.SAME), StraightFlush(5, holding(ACE, KING).negate().and(Rank.SEQUENCE).and(Suit.SAME), holding(ACE, KING).negate().and(Straight).and(Flush)), RoyalFlush(5, holding(ACE, KING).and(Rank.SEQUENCE).and(Suit.SAME), holding(ACE, KING).and(Straight).and(Flush)), FiveOfAKind(5, Rank.SAME, Rank.SAME); private final int required; private final Predicate
> possible; private final Predicate
> is; private Ranking(int required, Predicate
> possible, Predicate
> is) { this.required = required; this.possible = possible; this.is = Objects.requireNonNull(is); } ... public Predicate
> possible() { return t -> (possible == null || possible.test(subListTo(t, required()))); } ... }
TemporalAdjuster интерфейсы so
DayOfWeek предоставляет методы реализации для этих методов интерфейса. Реализация
Suit демонстрирует, как поля подкласса могут быть определены, реализуя предикат, и заданы путем определения пользовательского конструктора. Ключом к созданию плавного интерфейса, предоставляемого
Stream , является предикат , который должен протестировать компонент, который затем
, Конечно, fRank
и Suit
должны протестировать
Listhand = ...; int size = Math.min(5, hand.size()); boolean isStraight = Combinations.of(size, size, STRAIGHT.possible(), hand) .filter(Ranking.STRAIGHT) .anyMatch();
Ранг , Прямой
, если первые Карты
не являются последовательностью и т.д. Логика в
Ранг || , Прямой || , если первые || Карты || не являются последовательностью и т.д. Логика в || Ranking.find(Collection) и || Evaluator || демонстрирует более сложную логику. Резюме
Ранг , Прямой
, если первые Карты
не являются последовательностью и т.д. Логика в Ranking.find(Collection) и
Evaluator демонстрирует более сложную логику. Краткое описание Реализации
Предиката(КОМПОНЕНТА) Ранг
Оригинал: "https://dev.to/allenball/java-enums-as-predicates-bmd"