Лучший способ форматирования нескольких условий «или» в операторе if

#java #if-statement

Вопрос:

У меня есть оператор if со многими условиями (нужно проверить наличие 10 или 15 констант, чтобы увидеть, присутствуют ли какие-либо из них.)

Вместо того, чтобы писать что-то вроде:

 if (x == 12 || x == 16 || x == 19 || ...)
 

есть ли какой-либо способ отформатировать его следующим образом

 if x is [12, 16, 19]?
 

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

Ответы были очень полезными, но несколько человек попросили меня добавить больше деталей, поэтому я сделаю это, чтобы удовлетворить их любопытство. Я создавал класс проверки даты, который должен был убедиться, что дней не было> 30 в месяцах, в которых всего 30 дней (которых, я думаю, 4), и я писал оператор if, чтобы проверить такие вещи:

 if (day > 30 amp;amp; (month == 4 || month == 6 || month == 9 || month == 11))
 

Мне просто было интересно, есть ли более быстрый способ кодирования подобных вещей — многие из приведенных ниже ответов помогли.

Комментарии:

1. Можете ли вы привести лучший пример того, что вы пытаетесь сделать? Может быть, решение заключается в том, чтобы подумать об этом?

Ответ №1:

Я часто использую этот шаблон. Он очень компактный:

 // Define a constant in your class. Use a HashSet for performance
private static final Set<Integer> values = new HashSet<Integer>(Arrays.asList(12, 16, 19));

// In your method:
if (values.contains(x)) {
    ...
}
 

Здесь A HashSet используется для обеспечения хорошей производительности поиска — даже очень большие наборы хэшей могут выполняться contains() чрезвычайно быстро.

Если производительность не важна, вы можете закодировать ее суть в одну строку:

 if (Arrays.asList(12, 16, 19).contains(x))
 

но знайте, что ArrayList при каждом выполнении он будет создавать новое.

Комментарии:

1. if (Arrays.asList(12, 16, 19).содержит (x))

2. Я бы предпочел использовать Set List для этого a, а не a, но это не окажет никакого влияния на эти несколько элементов.

3. @Joachim Sauer включил вашу идею — она тоже хороша! HashSet будет намного быстрее

4. Использование Guava : private static final ImmutableSet<Integer> values = ImmutableSet.of(12, 16, 19);

Ответ №2:

Вы хотите переключиться на это??

 switch(x) {
    case 12:
    case 16:
    case 19: 
        //Do something
        break;
    default:
        //Do nothing or something else..
        break;
}
 

Ответ №3:

Если набор возможностей является «компактным» (т. Е. Наибольшее значение наименьшего значения, скажем, меньше 200), вы можете рассмотреть таблицу поиска. Это было бы особенно полезно, если бы у вас была такая структура, как

 if (x == 12 || x == 16 || x == 19 || ...)
else if (x==34 || x == 55 || ...)
else if (...)
 

Настройте массив со значениями, определяющими ветвь, которую нужно использовать (1, 2, 3 в приведенном выше примере), и тогда ваши тесты станут

 switch(dispatchTable[x])
{
    case 1:
        ...
        break;
    case 2:
        ...
        break;
    case 3:
        ...
        break;
}
 

Подходит это или нет, зависит от семантики проблемы.

Если массив не подходит, вы можете использовать a Map<Integer,Integer> , или, если вы просто хотите проверить членство в одном операторе, подойдет a Set<Integer> . Однако для простого оператора это большая огневая if мощь, поэтому без дополнительного контекста довольно сложно направить вас в правильном направлении.

Ответ №4:

Используйте какую-нибудь коллекцию — это сделает код более читаемым и скроет все эти константы. Простой способ — использовать список:

 // Declared with constants
private static List<Integer> myConstants = new ArrayList<Integer>(){{
    add(12);
    add(16);
    add(19);
}};

// Wherever you are checking for presence of the constant
if(myConstants.contains(x)){
    // ETC
}
 

Как указывает Богемиан, список констант может быть статическим, поэтому он доступен более чем в одном месте.

Для всех, кому интересно, список в моем примере использует инициализацию с двойными фигурными скобками. С тех пор как я столкнулся с этим недавно, я нашел его удобным для написания быстрых и грязных инициализаций списка.

Комментарии:

1. или if(Arrays.asList(new int[]{12,16,19}).contains(x)){ ... }

2. @Bala конечно! В любом случае список — это всего лишь пример используемой здесь коллекции. Как было предложено в одном из других ответов, set может быть лучше, чтобы гарантировать, что константы уникальны… Или хеш-таблица для ускорения поиска и т. Д.

Ответ №5:

Вы можете проверить наличие ключа map или посмотреть, есть ли он в наборе.

Однако, в зависимости от того, что вы на самом деле делаете, вы можете пытаться решить проблему неправильно 🙂

Ответ №6:

Нет, вы не можете сделать это на Java. однако вы можете написать метод следующим образом:

 boolean isContains(int i, int ... numbers) {
    // code to check if i is one of the numbers
    for (int n : numbers) {
        if (i == n) return true;
    }
    return false;
}
 

Ответ №7:

В Java 8 вы можете использовать примитивный поток:

 if (IntStream.of(12, 16, 19).anyMatch(i -> i == x))
 

но это может иметь небольшие накладные расходы (или нет), в зависимости от количества сравнений.