Рубрики
Без рубрики

Java Перечисляет как предикаты

В этой статье рассматривается расширение перечислений Java, используемых в качестве значений свойств в JavaBeans в сочетании с… С пометкой java, свободно владеет языком.

В этой статье рассматривается расширение 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;
    ...
}

позволит поддерживать плавные выражения, такие как:

    List hand = ...;

    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 static  Predicate> 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 static  List 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 static  List 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

    List hand = ...;
    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 должны протестировать

    List hand = ...;
    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"