我有一个包含许多条件的 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))
还有另一种写法更简洁/更高效吗?
我经常使用这种模式。非常紧凑:
在你的类中定义一个常量:
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
。
你想切换到这个吗?
switch(x) {
case 12:
case 16:
case 19:
//Do something
break;
default:
//Do nothing or something else..
break;
}
如果可能性集是“紧凑的”(即最大值 - 最小值小于 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
陈述来说,这已经是很大的火力了,所以如果没有更多的上下文,就很难引导你走向正确的方向。
使用某种类型的集合 - 这将使代码更具可读性并隐藏所有这些常量。一个简单的方法是使用列表:
// 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 指出常量列表可以是静态的,因此可以在多个地方访问它。
对于任何感兴趣的人,我的示例中的列表使用双括号初始化。自从我最近遇到它以来,我发现它很适合编写快速和脏列表初始化。
您可以查找地图键是否存在或查看它是否在集合中。
但是,根据您实际在做什么,您可能会错误地尝试解决问题:)
不,你不能在 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;
}
使用 Java 8,您可以使用原始流:
if (IntStream.of(12, 16, 19).anyMatch(i -> i == x))
但这可能会产生轻微的开销(或没有),具体取决于比较的数量。
这是基于上面评论的另一个答案,但更简单:
List numbers= Arrays.asList(1,2,3,4,5);
if(numbers.contains(x)){
//
}
在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)