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.
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
}
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)) {
// ...
}
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()))
{
}
ArrayUtils
peut être utile.
ArrayUtils.contains(new String[]{"1", "2"}, "1")
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.
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"));
}
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
}
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)
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.
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))) {...}
Classe Apache Commons Collection.
StringUtils.equalsAny (CharSequence string, CharSequence ... searchStrings)
Donc dans votre cas, ce serait
StringUtils.equalsAny (str, "val1", "val2", "val3");