88 votes

Quelle construction "if" est la plus rapide - déclaration ou opérateur ternaire ?

Il existe deux types de if déclarations en java - classique : if {} else {} et la sténographie : exp ? value1 : value2 . L'un est-il plus rapide que l'autre ou sont-ils identiques ?

déclaration :

int x;
if (expression) {
  x = 1;
} else {
  x = 2;
}

opérateur ternaire :

int x = (expression) ? 1 : 2;

34 votes

Je suppose qu'il n'y a absolument aucune différence. C'est juste de la syntaxe. A moins que les compilateurs soient quelque peu diaboliques (ou autre chose) et que je me trompe.

4 votes

L'avez-vous (micro)benchmarké ? Partagez les résultats.

3 votes

Les deux se retrouveront en prison. Il n'y aura pas de différence du tout. Et ne vous embêtez pas à décompiler le truc. La première chose que fait HotSpot est d'enlever tous les optimisations qui ont été appliquées par javac.

107voto

Jon Skeet Points 692016

Il n'y a qu'un seul type d'instruction "si". L'autre est une expression conditionnelle. Quant à savoir laquelle sera la plus performante : elles pourraient être compilées dans le même bytecode, et je m'attendrais à ce qu'elles se comportent de manière identique - ou si proche que vous ne voudriez certainement pas choisir l'une plutôt que l'autre en termes de performances.

Parfois, un if sera plus lisible, parfois l'opérateur conditionnel sera plus lisible. En particulier, je recommanderais d'utiliser l'opérateur conditionnel lorsque les deux opérandes sont simples et sans effet secondaire, alors que si le but principal des deux branches est leurs effets secondaires, j'utiliserais probablement un if déclaration.

Voici un exemple de programme et de bytecode :

public class Test {
    public static void main(String[] args) {
        int x;
        if (args.length > 0) {
            x = 1;
        } else {
            x = 2;
        }
    }

    public static void main2(String[] args) {
        int x = (args.length > 0) ? 1 : 2;
    }
}

Bytecode décompilé avec javap -c Test :

public class Test extends java.lang.Object {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1
       4: return

  public static void main(java.lang.String[]
    Code:
       0: aload_0
       1: arraylength
       2: ifle          10
       5: iconst_1
       6: istore_1
       7: goto          12
      10: iconst_2
      11: istore_1
      12: return

  public static void main2(java.lang.String[
    Code:
       0: aload_0
       1: arraylength
       2: ifle          9
       5: iconst_1
       6: goto          10
       9: iconst_2
      10: istore_1
      11: return
}

Comme vous pouvez le voir, il y a un léger différence dans le bytecode ici - si le istore_1 se produit à l'intérieur de la brance ou non (contrairement à ma tentative précédente très défectueuse :) mais je serais très surpris que le JITter aboutisse à un code natif différent.

0 votes

S/déclaration conditionnelle/expression conditionnelle/

1 votes

Je suppose que vous ne vouliez pas dire les deux. main y main2 pour être exactement les mêmes ?

0 votes

Impressionnant. Je ne savais pas qu'on pouvait compiler du code d'octet jusqu'à maintenant.

10voto

Victor Nicollet Points 16924

Vos deux exemples seront probablement compilés dans un bytecode identique ou presque identique, il ne devrait donc pas y avoir de différence de performance.

S'il y avait une différence dans la vitesse d'exécution, vous devriez quand même utiliser la version la plus idiomatique (qui serait la deuxième pour assigner une seule variable basée sur une condition simple et deux sous-expressions simples, et la première pour faire des opérations plus complexes ou des opérations qui ne tiennent pas sur une seule ligne).

8voto

Peter Lawrey Points 229686

Ce sont les mêmes. Les deux sont assez rapides, typiquement autour de 10-30 nano-secondes. (selon le mode d'utilisation) Ce laps de temps est-il important pour vous ?

Vous devez faire ce qui vous semble le plus clair.

4voto

Secko Points 2054

Juste pour ajouter à toutes les autres réponses :

La deuxième expression est souvent appelée opérateur/état tertiaire/ternaire. Elle peut être très utile car elle renvoie une expression. Parfois, elle rend le code plus clair pour les instructions courtes typiques.

4 votes

Un bon exemple pratique : en Java, si je dois rendre une chaîne finale en fonction du résultat d'une expression, je peux utiliser la syntaxe ternaire final String whichTable = (Integer.parseInt(clientId) > 500) ? "serverClients" : "offlineClients" ; Je peux ensuite utiliser la valeur de l'expression aux endroits où whichTable doit être final. Ce qui suit serait illégal : final String whichTable = "" ; if (Integer.parseInt(clientId) > 500) { whichTable = "serverClients" ; } else { whichTable = "offlineClients" ; }

0 votes

@JamesPerih Dans le cas d'un final Sur le terrain, vous pouvez utiliser les blocs constructeurs pour définir une valeur (bien que l'opérateur conditionnel soit un milliard de fois plus efficace), et avec les variables locales, vous pouvez attribuer une valeur avant la première utilisation dans le bloc de code dans lequel vous vous trouvez. Je pense que le seul cas où un ternaire donnerait un avantage par rapport à if-else c'est lorsqu'on appelle super(...) o this(...) à l'intérieur d'un constructeur.

3voto

Freddie Points 960

Ni l'un ni l'autre - ils seront compilés à l'identique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X