将一个String与一个表达式中的多个值进行比较

时间:2012-04-18 08:13:16

标签: java regex string

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

我想使用if语句将str与所有这些值进行比较,例如:

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.

15 个答案:

答案 0 :(得分:89)

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

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

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

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

答案 1 :(得分:13)

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

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

String str = "Val1";

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

答案 2 :(得分: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"));
}

答案 3 :(得分:1)

使用apache commons库https://stackoverflow.com/a/32241628/6095216

中的StringUtils进行另一种选择(类似于上面的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
}

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:0)

您可以使用Collections框架实现此目的。将所有选项放入集合中,例如Collection<String> options;

然后循环throgh这将你的字符串与列表元素进行比较,如果是,你可以返回一个布尔值为true,否则为false。

答案 6 :(得分: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))) {...} 

答案 7 :(得分:0)

Apache Commons Collection类。

StringUtils.equalsAny(CharSequence string,CharSequence ... searchStrings)

因此,您的情况应该是

StringUtils.equalsAny(str,“ val1”,“ val2”,“ val3”);

答案 8 :(得分:0)

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

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)

答案 9 :(得分: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())){
...
}

您可以通过检查变量str的非空性,并通过使用ArrayList加快对长列表的搜索来缓存创建后的列表,来应用一些错误预防措施:

// List of lower-case possibilities
List<String> list = new ArrayList<>(Arrays.asList("val1", "val2", "val3", ..., "val_n"));

if(str != null && list.contains(str.toLowerCase())){

}

答案 10 :(得分: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语句与

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

如果仅在一个地方使用它。

答案 11 :(得分:0)

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

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

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

测试:

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

答案 12 :(得分:0)

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

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

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

答案 13 :(得分:-2)

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

public static boolean contains(String s, Collection<String>c) {
    for (String ss : c) {
       if (s.equalsIgnoreCase(ss)) return true;
    }
    return false;
}

答案 14 :(得分:-3)

!string.matches("a|b|c|d") 

对我来说很好。