Лучший способ форматировать несколько "или" условий в операторе if (Java)
Простой вопрос, но Google не очень помогает.
У меня есть оператор if со многими условиями (нужно проверить наличие 10 или 15 констант, чтобы увидеть, присутствует ли кто-либо из них.)
Вместо того, чтобы писать что-то вроде:
if (x == 12 || x == 16 || x == 19 || ...)
есть ли способ форматировать его как
if x is [12, 16, 19]?
Просто интересно, есть ли более простой способ закодировать это, любая помощь оценивается.
Изменить. Ответы были очень полезными, но меня попросили добавить несколько деталей, чтобы я сделал это, чтобы насытить их любопытство. Я делал класс проверки даты, который должен был удостовериться, что дни не были > 30 в месяцах, которые имеют только 30 дней (из которых 4, я думаю), и я писал инструкцию if, чтобы проверить такие вещи:
if (day > 30 && (month == 4 || month == 6 || month == 9 || month == 11))
Мне просто интересно, был ли более быстрый способ кодировать такие вещи - многие из приведенных ниже ответов помогли:).
Ответы
Ответ 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
каждый раз, когда он выполняется.
Ответ 2
Вы хотите переключиться на это?
switch(x) {
case 12:
case 16:
case 19:
//Do something
break;
default:
//Do nothing or something else..
break;
}
Ответ 3
Нет, вы не можете сделать это на 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;
}
Ответ 4
Вы можете найти наличие ключа карты или посмотреть, есть ли он в наборе.
В зависимости от того, что вы на самом деле делаете, возможно, вы пытаетесь решить проблему неправильно:)
Ответ 5
Используйте какую-то коллекцию - это сделает код более читаемым и спрячет все эти константы. Простым способом будет со списком:
// 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
}
Как указывает Богемиан, список констант может быть статическим, поэтому он доступен в нескольких местах.
Для всех, кого интересует, в моем примере используется двойная инициализация скобок. Поскольку я столкнулся с этим в последнее время, я нашел приятным для написания быстрых и грязных инициализаций списка.
Ответ 6
Если набор возможностей "компактный" (т.е. наибольшее значение - наименьшее значение, скажем, меньше 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;
}
Независимо от того, подходит ли это, зависит от семантики проблемы.
Если массив не подходит, вы можете использовать Map<Integer,Integer>
, или если вы просто хотите проверить членство для одного оператора, это сделает Set<Integer>
. Тем не менее, много огневой мощи для простого оператора if
, поэтому без какого-либо контекста вам будет трудно вести вас в правильном направлении.
Ответ 7
С Java 8 вы можете использовать примитивный поток:
if (IntStream.of(12, 16, 19).anyMatch(i -> i == x))
но это может иметь небольшие накладные расходы (или нет), в зависимости от количества сравнений.