Проверить, содержит ли список хотя бы одно из других - перечисления

У меня есть перечисление:

public enum PermissionsEnum {
    ABC("Abc"),        
    XYZ("Xyz"),
    ....
}

И тогда у меня есть список Перечисления. Я хочу проверить, есть ли в моем списке хотя бы одно из перечислений. Сейчас я проверяю это итеративным подходом. Я также знаю, что есть способ сделать это, используя ||, проверяя list.contains(enum.ABC..) || list.contains(enum.XYZ) || ....

Есть ли способ лучше?

Этот вопрос показывает, как это сделать, если целевой список является списком строк, я хочу получить статус соответствия, если список является другим списком перечислений.

попробуйте !Collections.disjoint(list1, list2);, чтобы проверить, содержит ли список2 элементы из списка2

shahaf 11.04.2018 12:20

Что именно вы имеете в виду, говоря «Я хочу проверить, есть ли в моем списке (перечислений) хотя бы одно из перечислений»? Может быть, я неправильно понял, но если у вас List<PermissionEnum>, разве все элементы не входят в одно из перечислений? Кроме того, лучший способ хранить коллекцию перечислений - это EnumSet, потому что нет смысла иметь одно и то же разрешение дважды или более.

SeverityOne 11.04.2018 12:42
12
2
7 770
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете использовать Collections.disjoint().

Создайте еще один список с перечислениями, которые вы хотите проверить, а затем выполните Collections.disjoint(list, listOfEnumsToCheck). Он возвращает истину, если элементы не найдены. Если это ложь, по крайней мере, один элемент присутствует.

Я думаю, вы даже можете использовать Enum.values ​​(), чтобы он стал:

// Using ! to show there is at least one value
if (!Collections.disjoint(list, PermissionsEnum.values()) { 
     doStuff 
} 
Ответ принят как подходящий

Collections.disjoint возвращает true, если две указанные коллекции не имеют общих элементов. Если он возвращает false, значит, в вашем списке есть хотя бы одно из перечислений.

boolean contains = !Collections.disjoint(list, EnumSet.allOf(PermissionsEnum.class)));

Подход Stream API может быть:

EnumSet<PermissionsEnum> set = EnumSet.allOf(PermissionsEnum.class);
boolean contains = list.stream().anyMatch(set::contains);

(аналогично итеративному подходу, но с включенным распараллеливанием)

Вместо asList(PermissionsEnum.values()) я бы использовал EnumSet.allOf(PermissionsEnum.class), который возвращает Set с поиском O (1) и, кроме того, не требует копии массива всех значений. Кроме того, я не стал бы так быстро вставлять parallelStream(), поскольку маловероятно, что список настолько велик, что выполнение такой тривиальной операции параллельно имеет преимущество.

Holger 11.04.2018 13:42

Если можно использовать java-8.

Arrays.stream(PermissionsEnum.values()).anyMatch(list::contains);

Enum#values()

Returns an array containing the constants of this enum type.

Поэтому нам просто нужно обернуть его в поток и проверить, содержит ли список какие-либо значения. Важно помнить, что

anyMatch not evaluate the predicate on all elements if not necessary for determining the result.

Другими словами, он может вернуть истину, как только будет найден элемент, удовлетворяющий предикату.

По-видимому, более эффективный способ - использовать EnumSet.allOf(PermissionsEnum.class)::contains, потому что EnumSet.contains намного эффективнее, чем List.contains:

list.stream().anyMatch(EnumSet.allOf(PermissionsEnum.class)::contains)
list.stream().anyMatch(EnumSet.allOf(PermissionsEnum.class):‌​:contains) предпочтительнее, поскольку EnumSet.contains намного эффективнее, чем List.contains для всех распространенных реализаций List ...
Holger 11.04.2018 13:45

@Holger, большое спасибо за ваш комментарий, я этого не знал, обновлю свой ответ.

Anton Balaniuc 11.04.2018 14:38

у вас может быть статический список в перечислении Type Safe Enum Pattern, который будет действовать как главный список, который добавляется в конструктор перечисления. Таким образом, ваш главный список всегда содержит ровно по одному из каждого перечисления, и вы можете сравнивать его.

import java.util.ArrayList;

public class EnumeratedEnum {
    public static final ArrayList<EnumeratedEnum> Members=new ArrayList<>();
    private final String value;
    public String getValue() {return value;}
    private EnumeratedEnum(String value) {
        this.value=value;
        Members.add(this);
    }
    public static final EnumeratedEnum EnumOne=new EnumeratedEnum("someValue");
    public static final EnumeratedEnum EnumTwo=new EnumeratedEnum("someValue2");
    public static final EnumeratedEnum EnumThree=new EnumeratedEnum("someValue3");
    public static final EnumeratedEnum EnumFour=new EnumeratedEnum("someValue4");
    public static final EnumeratedEnum EnumFive=new EnumeratedEnum("someValue5");
}

Другие вопросы по теме