web-dev-qa-db-fra.com

Comparer une chaîne avec plusieurs valeurs dans une expression

J'ai une variable de chaîne, str avec les valeurs possibles, val1, val2 et val3.

Je veux comparer (avec la même casse) str à toutes ces valeurs en utilisant une instruction if, par exemple:

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

Existe-t-il un moyen d'éviter d'utiliser plusieurs opérateurs OR (||) et de comparer des valeurs dans une expression? Par exemple, comme ceci:

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

J'ai trouvé la meilleure solution. Ceci peut être réalisé avec RegEx: 

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

Pour la correspondance insensible à la casse:

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

En Java 8+, vous pouvez utiliser un Stream<T> et anyMatch(Predicate<? super T>) avec quelque chose comme

if (Stream.of("val1", "val2", "val3").anyMatch(str::equalsIgnoreCase)) {
    // ...
}
36
Elliott Frisch

Vous pouvez stocker toutes les chaînes avec lesquelles vous souhaitez comparer str dans une collection et vérifier si la collection contient str. Stockez toutes les chaînes de la collection en minuscules et convertissez str en minuscules avant d'interroger la collection. Par exemple:

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

String str = "Val1";

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

ArrayUtils peut être utile.

ArrayUtils.contains(new String[]{"1", "2"}, "1")
4
Jeffrey4l

Petite amélioration apportée à la réponse parfaitement valide de @ hmjd : vous pouvez utiliser la syntaxe suivante:

class A {

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

  // ...

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

  // ...
}

Il vous permet d’initialiser votre Set sur place.

3
Andrey Starodubtsev

Utilisez simplement var-args et écrivez votre propre méthode statique:

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"));
}
2
Neet

Encore une autre alternative (un peu similaire à https://stackoverflow.com/a/32241628/6095216 ci-dessus) en utilisant StringUtils à partir de la bibliothèque Apache commons: 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
}
1
Yury

Voici un test de performance avec plusieurs alternatives (certaines sont sensibles à la casse et d'autres non sensibles à la casse):

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

Sortie (seulement dans le pire des cas, c’est-à-dire quand il faut vérifier tous les éléments sans aucun match):

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)
0
Manuel Romeiro

Vous pouvez y parvenir avec le cadre Collections. Mettez toutes vos options dans une collection, par exemple Collection<String> options;

Ensuite, parcourez ceci pour comparer votre chaîne aux éléments de la liste. Si c'est le cas, vous pouvez renvoyer une valeur booléenne true et sinon false.

0
Tijo K Varghese

Rappelez-vous qu'en Java, une chaîne entre guillemets est toujours un objet Chaîne. Par conséquent, vous pouvez utiliser la fonction String contient () pour tester une plage de chaînes ou d'entiers à l'aide de cette méthode:

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

pour les chiffres c'est un peu plus compliqué mais ça marche toujours:

if ("1 4 5 9 10 17 23 96457".contains(String.valueOf(mNumAnswer))) {...} 
0
Stuart Walsh

Classe Apache Commons Collection.

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

Donc dans votre cas, ce serait

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

0
user3583333