74

我有一个字符串变量,str有可能的值val1val2val3

我想str使用 if 语句将(大小写相同)与所有这些值进行比较,例如:

if("val1".equalsIgnoreCase(str)||"val2".equalsIgnoreCase(str)||"val3".equalsIgnoreCase(str))
{
      //remaining code
}

有没有办法避免使用多个 OR (||) 运算符并比较一个表达式中的值?例如,像这样:

 if(("val1" OR "val2" OR "val3").equalsIgnoreCase(str)   //this is only an idea.
4

18 回答 18

123

我找到了更好的解决方案。这可以通过 RegEx 来实现:

if (str.matches("val1|val2|val3")) {
     // remaining code
}

对于不区分大小写的匹配:

if (str.matches("(?i)val1|val2|val3")) {
     // remaining code
}
于 2012-04-18T15:59:09.957 回答
79

在 Java 8+ 中,您可以使用 aStream<T>anyMatch(Predicate<? super T>)类似的东西

if (Stream.of("val1", "val2", "val3").anyMatch(str::equalsIgnoreCase)) {
    // ...
}
于 2016-12-03T21:08:22.587 回答
17

您可以将要比较str的所有字符串存储到一个集合中,并检查该集合是否包含str. 将集合中的所有字符串存储为小写,并str在查询集合之前转换为小写。例如:

Set<String> strings = new HashSet<String>();
strings.add("val1");
strings.add("val2");

String str = "Val1";

if (strings.contains(str.toLowerCase()))
{
}
于 2012-04-18T08:16:57.823 回答
10

使用 apache 公共库中的 StringUtils 的一种选择(有点类似于上面的https://stackoverflow.com/a/32241628/6095216):https://commons.apache.org/proper/commons-lang/apidocs/org/ apache/commons/lang3/StringUtils.html#equalsAnyIgnoreCase-java.lang.CharSequence-java.lang.CharSequence...-

if (StringUtils.equalsAnyIgnoreCase(str, "val1", "val2", "val3")) {
  // remaining code
}
于 2018-11-19T23:06:09.093 回答
7

这是一个具有多种选择的性能测试(一些区分大小写,另一些不区分大小写):

public static void main(String[] args) {
    // Why 4 * 4:
    // The test contains 3 values (val1, val2 and val3). Checking 4 combinations will check the match on all values, and the non match;
    // Try 4 times: lowercase, UPPERCASE, prefix + lowercase, prefix + UPPERCASE;
    final int NUMBER_OF_TESTS = 4 * 4;
    final int EXCUTIONS_BY_TEST = 1_000_000;
    int numberOfMatches;
    int numberOfExpectedCaseSensitiveMatches;
    int numberOfExpectedCaseInsensitiveMatches;
    // Start at -1, because the first execution is always slower, and should be ignored!
    for (int i = -1; i < NUMBER_OF_TESTS; i++) {
        int iInsensitive = i % 4;
        List<String> testType = new ArrayList<>();
        List<Long> timeSteps = new ArrayList<>();
        String name = (i / 4 > 1 ? "dummyPrefix" : "") + ((i / 4) % 2 == 0 ? "val" : "VAL" )+iInsensitive ;
        numberOfExpectedCaseSensitiveMatches = 1 <= i && i <= 3 ? EXCUTIONS_BY_TEST : 0;
        numberOfExpectedCaseInsensitiveMatches = 1 <= iInsensitive && iInsensitive <= 3 && i / 4 <= 1 ? EXCUTIONS_BY_TEST : 0;
        timeSteps.add(System.currentTimeMillis());
        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("List (Case sensitive)");
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if (Arrays.asList("val1", "val2", "val3").contains(name)) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseSensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("Set (Case sensitive)");
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if (new HashSet<>(Arrays.asList(new String[] {"val1", "val2", "val3"})).contains(name)) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseSensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("OR (Case sensitive)");
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if ("val1".equals(name) || "val2".equals(name) || "val3".equals(name)) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseSensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("OR (Case insensitive)");
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if ("val1".equalsIgnoreCase(name) || "val2".equalsIgnoreCase(name) || "val3".equalsIgnoreCase(name)) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseInsensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("ArraysBinarySearch(Case sensitive)");
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if (Arrays.binarySearch(new String[]{"val1", "val2", "val3"}, name) >= 0) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseSensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("Java8 Stream (Case sensitive)");
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if (Stream.of("val1", "val2", "val3").anyMatch(name::equals)) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseSensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("Java8 Stream (Case insensitive)");
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if (Stream.of("val1", "val2", "val3").anyMatch(name::equalsIgnoreCase)) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseInsensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("RegEx (Case sensitive)");
        // WARNING: if values contains special characters, that should be escaped by Pattern.quote(String)
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if (name.matches("val1|val2|val3")) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseSensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("RegEx (Case insensitive)");
        // WARNING: if values contains special characters, that should be escaped by Pattern.quote(String)
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            if (name.matches("(?i)val1|val2|val3")) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseInsensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        numberOfMatches = 0;
        testType.add("StringIndexOf (Case sensitive)");
        // WARNING: the string to be matched should not contains the SEPARATOR!
        final String SEPARATOR = ",";
        for (int j = 0; j < EXCUTIONS_BY_TEST; j++) {
            // Don't forget the SEPARATOR at the begin and at the end!
            if ((SEPARATOR+"val1"+SEPARATOR+"val2"+SEPARATOR+"val3"+SEPARATOR).indexOf(SEPARATOR + name + SEPARATOR)>=0) {
                numberOfMatches++;
            }
        }
        if (numberOfMatches != numberOfExpectedCaseSensitiveMatches) {
            throw new RuntimeException();
        }
        timeSteps.add(System.currentTimeMillis());

        //-----------------------------------------
        StringBuffer sb = new StringBuffer("Test ").append(i)
                .append("{ name : ").append(name)
                .append(", numberOfExpectedCaseSensitiveMatches : ").append(numberOfExpectedCaseSensitiveMatches)
                .append(", numberOfExpectedCaseInsensitiveMatches : ").append(numberOfExpectedCaseInsensitiveMatches)
                .append(" }:\n");
        for (int j = 0; j < testType.size(); j++) {
            sb.append(String.format("    %4d ms with %s\n", timeSteps.get(j + 1)-timeSteps.get(j), testType.get(j)));
        }
        System.out.println(sb.toString());
    }
}

输出(只有最坏的情况,即必须检查所有不匹配的元素):

Test 4{ name : VAL0, numberOfExpectedCaseSensitiveMatches : 0, numberOfExpectedCaseInsensitiveMatches : 0 }:
  43 ms with List (Case sensitive)
 378 ms with Set (Case sensitive)
  22 ms with OR (Case sensitive)
 254 ms with OR (Case insensitive)
  35 ms with ArraysBinarySearch(Case sensitive)
 266 ms with Java8 Stream (Case sensitive)
 531 ms with Java8 Stream (Case insensitive)
1009 ms with RegEx (Case sensitive)
1201 ms with RegEx (Case insensitive)
 107 ms with StringIndexOf (Case sensitive)

Warpspeed SCP 提供的输出,更改测试以填充循环之外的集合,模拟当要测试的值列表永远不会更改时的代码(并且可以缓存集合)。

(由于是在不同的环境下执行的,本次测试的时间不要和上一次比较,只比较同一个测试不同策略的时间):

Test 4{ name : VAL0, numberOfExpectedCaseSensitiveMatches : 0, numberOfExpectedCaseInsensitiveMatches : 0 }:
    26 ms with List (Case sensitive)
    6 ms with Set (Case sensitive)
    12 ms with OR (Case sensitive)
    371 ms with OR (Case insensitive)
    14 ms with ArraysBinarySearch(Case sensitive)
    100 ms with Java8 Stream (Case sensitive)
    214 ms with Java8 Stream (Case insensitive)
    773 ms with RegEx (Case sensitive)
    946 ms with RegEx (Case insensitive)
    37 ms with StringIndexOf (Case sensitive)
于 2019-06-21T15:28:12.157 回答
5

ArrayUtils可能会有所帮助。

ArrayUtils.contains(new String[]{"1", "2"}, "1")
于 2015-08-27T05:53:02.937 回答
3

对完全有效的@hmjd 答案的小改进:您可以使用以下语法:

class A {

  final Set<String> strings = new HashSet<>() {{
    add("val1");
    add("val2");
  }};

  // ...

  if (strings.contains(str.toLowerCase())) {
  }

  // ...
}

它允许您Set就地初始化您。

于 2015-09-14T10:51:15.427 回答
2

只需使用 var-args 并编写自己的静态方法:

public static boolean compareWithMany(String first, String next, String ... rest)
{
    if(first.equalsIgnoreCase(next))
        return true;
    for(int i = 0; i < rest.length; i++)
    {
        if(first.equalsIgnoreCase(rest[i]))
            return true;
    }
    return false;
}

public static void main(String[] args)
{
    final String str = "val1";
    System.out.println(compareWithMany(str, "val1", "val2", "val3"));
}
于 2012-04-18T08:19:43.037 回答
2

Apache Commons Collection 类。

StringUtils.equalsAny(CharSequence 字符串,CharSequence...searchStrings)

所以在你的情况下,它会是

StringUtils.equalsAny(str, "val1", "val2", "val3");

于 2018-12-26T18:40:08.600 回答
1

从 Java 9 开始,您可以使用以下任一

List.of("val1", "val2", "val3").contains(str.toLowerCase())

Set.of("val1", "val2", "val3").contains(str.toLowerCase());
于 2020-03-19T01:16:33.787 回答
1

建议的解决方案很多,大多数是可行的解决方案。但是我必须在这里补充一点,人们建议使用正则表达式 iestr.matches("val1|val2|val3")是可以的

  1. 如果多次调用方法/代码,则性能不佳
  2. 它不是空安全的

我建议改用 apache commons lang3 StringUtils.equalsAny(str, "val1", "val2", "val3")stringUtils

测试:

public static void main(String[] args) {
        String var = "val1";
        long t, t1 = 0, t2 = 0;

        for (int i = 0; i < 1000; i++) {
            t = System.currentTimeMillis();
            var.matches("val1|val2|val3");
            t1 += System.currentTimeMillis() - t;

            t = System.currentTimeMillis();
            StringUtils.equalsAny(var, "val1", "val2", "val3");
            t2 += System.currentTimeMillis() - t;
        }
        System.out.println("Matches took + " + t1 + " ms\nStringUtils took " + t2 + " ms");
    }

1000 次迭代后的结果:

Matches took + 18 ms
StringUtils took 7 ms
于 2020-06-18T09:40:28.910 回答
1

对于那些来这里进行精确平等检查(不忽略大小写)的人,我发现

if (Arrays.asList(str1, str2, str3).contains(strToCheck)) {
    ...
}

是最简洁的解决方案之一,并且在 Java 7 上可用。

于 2020-07-31T11:45:34.597 回答
0

您可以使用 Collections 框架来实现这一点。将您的所有选项放在一个集合中,例如Collection<String> options

然后循环通过它来比较你的字符串和列表元素,如果是,你可以返回一个布尔值 true,否则返回 false。

于 2012-04-18T08:21:10.493 回答
0

请记住,在 Java 中,带引号的 String 仍然是 String 对象。因此,您可以使用 String 函数 contains() 使用此方法测试一系列字符串或整数:

if ("A C Viking G M Ocelot".contains(mAnswer)) {...}

对于数字,它涉及更多但仍然有效:

if ("1 4 5 9 10 17 23 96457".contains(String.valueOf(mNumAnswer))) {...} 
于 2017-01-19T08:46:22.703 回答
0

很抱歉回答这个老问题,对于 Java 8+,我认为最好的解决方案是 Elliott Frisch ( Stream.of("str1", "str2", "str3").anyMatches(str::equalsIgnoreCase)) 提供的解决方案,但它似乎缺少最古老的 Java 版本的最简单解决方案之一:

if(Arrays.asList("val1", "val2", "val3", ..., "val_n").contains(str.toLowerCase())){
//...
}

您可以通过检查 variable 的非空性str并在创建后缓存列表来应用一些错误预防。

// List of lower-case possibilities
final List<String> list = Arrays.asList("val1", "val2", "val3", ..., "val_n");
for(String str : somethingYouCouldTheReadStringFrom()){
  if(str != null && list.contains(str.toLowerCase())){
    //...
  }
}
于 2020-02-03T09:08:28.260 回答
0

既然这个问题已经重新打开,我不妨提出一个enum解决方案。

enum ValidValues {
   VAL1, VAL2, VAL3;

   public static boolean isValid(String input) {
       return Stream.of(ValidValues.values())
                    .map(ValidValues::name)
                    .anyMatch(s -> s.equalsIgnoreCase(input));
   }
}

或者你可以只使用流语句

Stream.of("val1", "val2", "val3")
      .anyMatch(s -> s.equalsIgnoreCase(str))

如果你只在一个地方使用它。

于 2020-02-03T09:18:48.517 回答
-2
!string.matches("a|b|c|d") 

对我来说很好。

于 2016-11-10T10:09:01.953 回答
-3

不,不存在这种可能性。尽管如此,人们可以想象:

public static boolean contains(String s, Collection<String>c) {
    for (String ss : c) {
       if (s.equalsIgnoreCase(ss)) return true;
    }
    return false;
}
于 2012-04-18T08:17:26.283 回答