¿Cómo es más eficaz la cadena en la instrucción switch que la statement if-else correspondiente?

La documentación de Java dice

El comstackdor de Java genera bytecode generalmente más eficiente a partir de sentencias switch que usan objetos String que de sentencias if-then-else encadenadas.

AFAIK incluso String in switch usa .equals() internamente de una manera sensible a mayúsculas y minúsculas. Entonces, ¿qué significan ellos en este contexto? Comstackción más rápida? ¿Menos bytecodes? ¿mejor interpretación?

El uso de una instrucción switch es más rápido que igual (pero solo notablemente cuando hay más que unas pocas cadenas) porque primero usa el hashCode de la cadena que se hashCode para determinar el subconjunto de las cadenas que posiblemente coincidan. Si más de una cadena en las tags de casos tiene el mismo hashCode, la JVM realizará llamadas secuenciales a equals e incluso si solo hay una cadena en las tags de casos que tiene un hashCode, la JVM necesita llamar a equals para confirmar que la cadena en la etiqueta de la caja es realmente igual a la de la expresión del interruptor.

El rendimiento en tiempo de ejecución de un switch en objetos String es comparable a una búsqueda en un HashMap .

Este pedazo de código:

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

Se comstack internamente y se ejecuta como este fragmento de código:

(no literalmente, pero si descomstacks ambas partes del código, ves que se produce exactamente la misma secuencia de acciones)

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

En general , las sentencias de cambio son mejores porque son (en términos generales) O(1) , mientras que una cadena de if-else es O(n)

Tener n condiciones podría dar como resultado n comparaciones utilizando sentencias if-else encadenadas.

Una instrucción switch puede “saltar” directamente a la condición apropiada (como un mapa) o al caso predeterminado, convirtiéndolo en O(1) .

Este es un fragmento de código de bytes generado a partir del ejemplo en los documentos:

  INVOKEVIRTUAL java/lang/String.hashCode ()I LOOKUPSWITCH -2049557543: L2 -1984635600: L3 -1807319568: L4 

el uso de LOOKUPSWITCH tiene un mejor rendimiento en comparación con la lógica if-else