Formulaire abrégé pour l'instruction Java If Else


J'ai une méthode qui vérifie les valeurs nulles. Est-il un moyen de réduire le nombre de lignes de la méthode? Actuellement, le code semble "sale":

private int similarityCount (String one, String two) {

    if (one == null && two == null) {
        return 1;
    } else if (one == null && two != null) {
        return 2;
    } else if (one != null && two == null) {
        return 3;
    } else {
        if(isMatch(one, two))
             return 4;
        return 5;
    }

}
Author: Allan Pereira, 2017-02-02

10 answers

private int similarityCount (String one, String two) {

    if (one == null && two == null) {
        return 1;
    } 

    if (one == null) {
        return 2;
    } 

    if (two == null) {
        return 3;
    } 

    if (isMatch(one, two)) {
        return 4;
    }
    return 5;
}
 62
Author: Manh Le, 2017-02-02 17:58:42

Je préfère les conditions imbriquées dans de tels cas:

private int similarityCount (String one, String two) {
    if (one==null) {
        if (two==null) {
            return 1;
        } else {
            return 2;
        }
    } else {
        if (two==null) {
            return 3;
        } else {
            return isMatch(one, two) ? 4 : 5;
        }
    }
}

Bien sûr, vous pouvez obtenir une version plus courte en utilisant des opérateurs conditionnels plus ternaires.

private int similarityCount (String one, String two) {  
    if (one==null) {
        return (two==null) ? 1 : 2;
    } else {
        return (two==null) ? 3 : isMatch(one, two) ? 4 : 5;
    }
}

Ou même (maintenant cela devient moins lisible):

private int similarityCount (String one, String two) {  
    return (one==null) ? ((two==null) ? 1 : 2) : ((two==null) ? 3 : isMatch(one, two) ? 4 : 5);
}
 33
Author: Eran, 2017-02-02 10:34:22

Puisque le but réel de la fonction semble être de gérer des objets non-null en les faisant correspondre, je gérerais toutes les vérifications null dans une instruction guard au début.

, Puis, une fois que vous avez établi qu'aucun argument n'est null, vous pouvez gérer la logique réelle:

private int similarityCount(String a, String b) {
    if (a == null || b == null) {
        return a == b ? 1 : a == null ? 2 : 3;
    }

    return isMatch(a, b) ? 4 : 5;
}

Ceci est à la fois plus concis et plus lisible que les autres options.

Cela dit, les fonctions réelles ne renverraient généralement pas de tels codes numériques. Sauf si votre méthode a été simplifiée pour illustrez le problème, je vous exhorte fortement à reconsidérer la logique et à écrire quelque chose de semblable à ce qui suit:

private boolean similarityCount(String a, String b) {
    if (a == null || b == null) {
        throw new NullPointerException();
    }

    return isMatch(a, b);
}

Ou:

private boolean similarityCount(String a, String b) {
    if (a == null) {
        throw new IllegalArgumentException("a");
    }
    if (b == null) {
        throw new IllegalArgumentException("b");
    }

    return isMatch(a, b);
}

Ces approches seraient plus conventionnelles. D'un autre côté, ils peuvent déclencher une exception. Nous pouvons éviter cela en renvoyant un java.util.Optional<Boolean> en Java 8:

private Optional<Boolean> similarityCount(String a, String b) {
    if (a == null || b == null) {
        return Optional.empty();
    }

    return Optional.of(isMatch(a, b));
}

À première vue, cela peut sembler ne pas être mieux que de retourner nullmais les options sont en fait bien supérieures.

 25
Author: Konrad Rudolph, 2017-02-02 12:10:59

Le code semble assez clair pour moi. Vous pouvez le raccourcir avec les opérateurs nesting et ternary:

if(one==null) {
    return two==null ? 1 : 2;
}
if(two==null) {
    return 3;
} 
return isMatch(one,two) ? 4 : 5;
 9
Author: default locale, 2017-02-02 10:33:12

Cela peut être fait en une seule ligne en utilisant l'opérateur conditionnel Java:

return (one==null?(two==null?1:2):(two==null?3:(isMatch(one,two)?4:5)));
 5
Author: SachinSarawgi, 2017-02-02 10:51:55

Vous pouvez créer une pseudo-table de recherche. Certaines personnes froncent les sourcils sur les opérateurs ternaires imbriqués et cela dépend fortement des espaces pour la lisibilité, mais cela peut être une approche très lisible du retour conditionnel:

private int similarityCount (String one, String two) {
    return (one == null && two == null) ? 1
         : (one == null && two != null) ? 2
         : (one != null && two == null) ? 3
         : isMatch(one, two)            ? 4
         :                                5;
}
 4
Author: Dancrumb, 2017-02-02 16:41:40

J'aime les expressions.

private static int similarityCount (String one, String two) {    
    return one == null ? 
        similarityCountByTwoOnly(two) : 
        two == null ? 3 : (isMatch(one, two) ? 4 : 5)
    ;
}

private static int similarityCountByTwoOnly(String two) {
    return two == null ? 1 : 2;
}

En aparté, je contesterais probablement pourquoi vous faites cela. Je suppose que vous feriez une sorte de vérification sur l'entier retourné après l'avoir évalué et branchez votre logique en fonction de celui-ci. Si tel est le cas, vous venez de faire une vérification moins lisible de null où l'utilisateur de votre méthode doit comprendre le contrat implicite dans la valeur de l'entier.

Aussi, voici une solution simple pour quand vous devez vérifier si les chaînes sont égal quand ils peuvent être nuls:

boolean same = one == null ? two == null : one.equals(two);
 1
Author: Erik Madsen, 2017-02-02 15:57:12

Se débarrasser des déclarations IF est très amusant. L'utilisation d'une carte est une façon de le faire. Cela ne correspond pas exactement à ce cas à cause de l'appel à isMatch, mais je l'offre comme alternative qui coupe le corps de la méthode similarityCount en une seule ligne avec un IF

Le code suivant a deuxFs. Si GetOrDefault n'évaluait pas le deuxième argument, il pourrait être réduit à un. Malheureusement, il le fait, la vérification nulle à l'intérieur d'isMatch est nécessaire.

Vous pourriez aller beaucoup plus loin avec cela si vous le voulais. Par exemple, isMatch pourrait renvoyer 4 ou 5 plutôt qu'un booléen, ce qui vous aiderait à simplifier davantage.

import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import java.util.Map;

public class SimilarityCount {

    private Map<SimilarityCountKey, Integer> rtn = ImmutableMap.of(new SimilarityCountKey(null, null), 1, new SimilarityCountKey(null, ""), 2, new SimilarityCountKey("", null), 3);

    public int similarityCount(String one, String two) {
        return rtn.getOrDefault(new SimilarityCountKey(one, two), isMatch(one, two) ? 4 : 5);
    }

    private boolean isMatch(String one, String two) {
        if (one == null || two == null) {
            return false;
        }
        return one.equals(two);
    }

    private class SimilarityCountKey {
        private final boolean one;
        private final boolean two;

        public SimilarityCountKey(String one, String two) {
            this.one = one == null;
            this.two = two == null;
        }

        @Override
        public boolean equals(Object obj) {
            return EqualsBuilder.reflectionEquals(this, obj);
        }

        @Override
        public int hashCode() {
            return HashCodeBuilder.reflectionHashCode(this);
        }
    }
}

Au cas où quelqu'un d'autre craque à une autre solution, voici quelques tests pour vous aider à démarrer

 import org.junit.Assert;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;

public class SimilarityCountTest {

    @Test
    public void one(){
        Assert.assertThat(new SimilarityCount().similarityCount(null,null), is(1));
    }

    @Test
    public void two(){
        Assert.assertThat(new SimilarityCount().similarityCount(null,""), is(2));
    }

    @Test
    public void three(){
        Assert.assertThat(new SimilarityCount().similarityCount("",null), is(3));
    }

    @Test
    public void four(){
        Assert.assertThat(new SimilarityCount().similarityCount("",""), is(4));
    }

    @Test
    public void five(){
        Assert.assertThat(new SimilarityCount().similarityCount("a","b"), is(5));
    }

}
 0
Author: Mark Chorley, 2017-02-02 13:21:49

Cela devrait être légèrement plus rapide si ni l'un ni l'autre n'est null, car il n'exécute qu'une seule instruction 'if' dans ce cas.

private int similarityCount (String one, String two) {

    if (one == null || two == null) {  // Something is null
        if (two != null) { // Only one is null
            return 2;
        }

        if (one != null) { // Only two is null
            return 3;
        }

        return 1; // Both must be null
    } 

    return isMatch(one, two) ? 4 : 5;
}
 0
Author: user7507190, 2017-02-02 17:01:55

LOL...La programmation n'est pas un concours de beauté. Vos codes

if (one == null && two == null) {
        return 1;
} else if (one == null && two != null) {
        return 2;
    } else if (one != null && two == null) {
        return 3;
    } else {
        if(isMatch(one, two))
             return 4;
        return 5;
    }

Ne sont PAS sales, mais assez beaux pour les profanes, et les experts aussi. Que pensez-vous du codage suivant

return one == null && two == null ? 1:
       one == null && two != null ? 2:
       one != null && two == null ? 3:
       isMatch(one, two) ? 4 : 5;

Génial, n'est-ce pas ? Eh bien, pour les profanes, il est "vaudou", pour les "experts"...il ne faut pas parler de "goût", de "politique" et de "religion". MAIS du point de vue de la performance, il en est ainsi:

  • la 1ère version est plus rapide
  • la 2ème version est plus maladroite (ou plus lent)

POURQUOI'? Il suffit de le compiler " javac-g: none Test5*.java " et comparez les bytecodes générés. Je l'ai fait et voici les résultats:

Première version:

public class Test5 {
    public static void main(String[] args) {
        String one = "1";
        String two = "2";
        System.out.println(check(one, two));
    }
    private static int check(String one, String two) {
        if (one == null && two == null) {
                return 1;
        } else if (one == null && two != null) {
                return 2;
            } else if (one != null && two == null) {
                return 3;
            } else {
                if(isMatch(one, two))
                     return 4;
                return 5;
            }
    }
    public static boolean isMatch(String a, String b) {
        return true;
    }
}

Produit 570 octets

Deuxième version:

public class Test5a {
    public static void main(String[] args) {
        String one = "1";
        String two = "2";
        System.out.println(check(one, two));
    }
    private static int check(String one, String two) {
        return one == null && two == null ? 1:
               one == null && two != null ? 2:
               one != null && two == null ? 3:
               isMatch(one, two) ? 4 : 5;
    }
    public static boolean isMatch(String a, String b) {
        return true;
    }
}

Produit 581 octets

Il est clair que 11 octets doivent être traités et cela prend du temps...plus une application a de codes "excessifs", plus elle aura de mauvaises performances.

 0
Author: Voodoo, 2017-02-02 17:02:48