如何在 if 语句中格式化多个“或”条件

问题描述 投票:0回答:9

我有一个包含许多条件的 if 语句(必须检查 10 或 15 个常量以查看其中是否存在。)

而不是写这样的东西:

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

有什么办法可以格式化它

if x is [12, 16, 19]?

我正在制作一个日期验证类,需要确保只有 30 天(我认为有 4 天)的月份中的天数不超过 30 天,并且我正在编写一个 if 语句来检查如下内容:

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

还有另一种写法更简洁/更高效吗?

java syntax if-statement
9个回答
62
投票

我经常使用这种模式。非常紧凑:

在你的类中定义一个常量:

private static final Set<Integer> VALUES = Set.of(12, 16, 19);    
// Pre Java 9 use: VALUES = new HashSet<Integer>(Arrays.asList(12, 16, 19));

在你的方法中:

if (VALUES.contains(x)) {
    ...
}

Set.of()
返回
HashSet
,即使对于非常大的集合,其性能也非常好。

如果性能不重要,您可以将其要点编码为一行以减少代码占用:

if (Set.of(12, 16, 19).contains(x))

但要知道它每次执行时都会创建一个新的

Set


11
投票

你想切换到这个吗?

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;
}

这是否合适取决于问题的语义。

如果数组不合适,您可以使用

Map<Integer,Integer>
,或者如果您只想测试单个语句的成员资格,则可以使用
Set<Integer>
。然而,对于一个简单的
if
陈述来说,这已经是很大的火力了,所以如果没有更多的上下文,就很难引导你走向正确的方向。


3
投票

使用某种类型的集合 - 这将使代码更具可读性并隐藏所有这些常量。一个简单的方法是使用列表:

// 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
}

Bohemian 指出常量列表可以是静态的,因此可以在多个地方访问它。

对于任何感兴趣的人,我的示例中的列表使用双括号初始化。自从我最近遇到它以来,我发现它很适合编写快速和脏列表初始化。


3
投票

您可以查找地图键是否存在或查看它是否在集合中。

但是,根据您实际在做什么,您可能会错误地尝试解决问题:)


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;
}

3
投票

使用 Java 8,您可以使用原始流:

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

但这可能会产生轻微的开销(或没有),具体取决于比较的数量。


0
投票

这是基于上面评论的另一个答案,但更简单:

List numbers= Arrays.asList(1,2,3,4,5);
if(numbers.contains(x)){
     //
}

0
投票

在java8中还有另一种使用Stream.of的方法:

Stream.of(a==1, b.equals("something"), c > 23, rocket.wasFired()).anyMatch(Boolean.TRUE::equals)

当有多个条件时,您必须检查保存一些代码行。

我认为概念上更好,因为主要目的是检查多重或复合谓词是否为真,而不是检查容器中元素是否存在。

在主要问题案例中,可能如下:

Stream.of(month == 4, month == 6, month == 9, month == 11).anyMatch(Boolean.TRUE::equals)
© www.soinside.com 2019 - 2024. All rights reserved.