Le compilateur Java génère généralement un bytecode plus efficace à partir des instructions switch qui utilisent des objets String que des instructions if-then-else chaînées.
AFAIK, même String dans le commutateur utilise .equals()
en interne de manière sensible à la casse. Alors, quelle efficacité signifient-ils dans ce contexte? Compilation plus rapide? Moins de bytecodes? meilleure performance?
L'utilisation d'une instruction switch est plus rapide qu'égal (mais seulement de façon notable lorsqu'il y a plus que quelques chaînes) car elle utilise d'abord le hashCode
de la chaîne sur laquelle switch
pour déterminer le sous-ensemble du chaînes qui pourraient éventuellement correspondre. Si plusieurs chaînes dans les étiquettes de cas ont le même hashCode, la JVM effectuera des appels séquentiels à equals
et même s'il n'y a qu'une seule chaîne dans les étiquettes de cas qu'un hashCode, la JVM doit appeler equals
pour confirmer que la chaîne de l'étiquette de cas est vraiment égale à celle de l'expression de commutation.
Les performances d'exécution d'un commutateur sur des objets String sont comparables à une recherche dans un HashMap
.
Ce morceau de code:
public static void main(String[] args) {
String s = "Bar";
switch (s) {
case "Foo":
System.out.println("Foo match");
break;
case "Bar":
System.out.println("Bar match");
break;
}
}
Est compilé en interne et exécuté comme ce morceau de code:
(pas littéralement, mais si vous décompilez les deux morceaux de code, vous voyez que la même séquence d'actions se produit)
final static int FOO_HASHCODE = 70822; // "Foo".hashCode();
final static int BAR_HASHCODE = 66547; // "Bar".hashCode();
public static void main(String[] args) {
String s = "Bar";
switch (s.hashCode()) {
case FOO_HASHCODE:
if (s.equals("Foo"))
System.out.println("Foo match");
break;
case BAR_HASHCODE:
if (s.equals("Bar"))
System.out.println("Bar match");
break;
}
}
Dans general, les instructions switch sont meilleures car elles sont (en gros) O(1)
, tandis qu'une chaîne de if-else
Est O(n)
Le fait d'avoir des conditions n
peut entraîner jusqu'à n
comparaisons à l'aide d'une instruction chaînée if-else
.
Une instruction switch peut "sauter" directement à la condition appropriée (comme une carte) ou au cas par défaut, ce qui en fait O(1)
.
Ceci est un fragment de bytecode généré à partir d'un exemple dans les documents:
INVOKEVIRTUAL Java/lang/String.hashCode ()I
LOOKUPSWITCH
-2049557543: L2
-1984635600: L3
-1807319568: L4
l'utilisation de LOOKUPSWITCH est plus performante que la logique if-else