web-dev-qa-db-fra.com

Meilleure façon de formater plusieurs conditions 'ou' dans une instruction if (Java)

Une question simple, mais Google n'a pas beaucoup aidé.

J'ai une instruction if avec de nombreuses conditions (je dois vérifier 10 ou 15 constantes pour voir si certaines d'entre elles sont présentes.)

Au lieu d'écrire quelque chose comme:

if (x == 12 || x == 16 || x == 19 || ...)

est-il possible de le formater comme

if x is [12, 16, 19]?

Je me demande simplement s'il existe un moyen plus simple de coder cela, toute aide appréciée.

Modifier : Les réponses ont été très utiles, mais quelques personnes m'ont demandé d'ajouter plus de détails, donc je ferai cela pour rassasier leur curiosité. Je faisais une classe de validation de date qui devait m'assurer que les jours n'étaient pas> 30 dans les mois qui n'ont que 30 jours (dont il y en a 4, je pense) et j'écrivais une instruction if pour vérifier des choses comme ceci:

if (day > 30 && (month == 4 || month == 6 || month == 9 || month == 11))

Je me demandais simplement s'il y avait un moyen plus rapide de coder des choses comme ça - la plupart des réponses ci-dessous ont aidé :).

42
Anthony

J'utilise souvent ce type de motif. C'est très compact:

// Define a constant in your class. Use a HashSet for performance
private static final Set<Integer> values = new HashSet<Integer>(Arrays.asList(12, 16, 19));

// In your method:
if (values.contains(x)) {
    ...
}

Un HashSet est utilisé ici pour donner de bonnes performances de recherche - même de très grands ensembles de hachage sont capables d'exécuter contains() extrêmement rapidement.

Si les performances ne sont pas importantes, vous pouvez en coder l'essentiel sur une seule ligne:

if (Arrays.asList(12, 16, 19).contains(x))

mais sachez qu'il créera un nouveau ArrayList à chaque exécution.

46
Bohemian

Voulez-vous passer à cela ??

switch(x) {
    case 12:
    case 16:
    case 19: 
        //Do something
        break;
    default:
        //Do nothing or something else..
        break;
}
10
Gevorg

Vous pouvez rechercher la présence d'une clé de carte ou voir si elle est dans un ensemble.

Selon ce que vous faites réellement faire, cependant, vous essayez peut-être de résoudre le problème mal :)

3
Dave Newton

Utilisez une collection quelconque - cela rendra le code plus lisible et masquera toutes ces constantes. Une manière simple serait avec une liste:

// 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
}

Comme le fait remarquer Bohemian, la liste des constantes peut être statique, elle est donc accessible à plusieurs endroits.

Pour toute personne intéressée, la liste de mon exemple utilise initialisation à double accolade . Depuis que je l'ai rencontré récemment, je l'ai trouvé agréable pour écrire des initialisations de liste rapides et sales.

3
filip-fku

Si l'ensemble des possibilités est "compact" (c'est-à-dire la plus grande valeur - la plus petite valeur est, par exemple, inférieure à 200), vous pouvez envisager une table de recherche. Ce serait particulièrement utile si vous aviez une structure comme

if (x == 12 || x == 16 || x == 19 || ...)
else if (x==34 || x == 55 || ...)
else if (...)

Configurez un tableau avec des valeurs identifiant la branche à prendre (1, 2, 3 dans l'exemple ci-dessus), puis vos tests deviennent

switch(dispatchTable[x])
{
    case 1:
        ...
        break;
    case 2:
        ...
        break;
    case 3:
        ...
        break;
}

Que cela soit approprié ou non dépend de la sémantique du problème.

Si un tableau n'est pas approprié, vous pouvez utiliser un Map<Integer,Integer>, ou si vous souhaitez simplement tester l'appartenance pour une seule instruction, un Set<Integer> ferait. C'est beaucoup de puissance de feu pour une simple instruction if, cependant, sans plus de contexte, il est difficile de vous guider dans la bonne direction.

3
Jim Garrison

Non, vous ne pouvez pas faire cela en Java. vous pouvez cependant écrire une méthode comme suit:

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;
}
3
fastcodejava

Avec Java 8, vous pouvez utiliser un flux primitif:

if (IntStream.of(12, 16, 19).anyMatch(i -> i == x))

mais cela peut avoir un léger surcoût (ou non), selon le nombre de comparaisons.

2
assylias