2015-01-16 8 views
16

Un HashMap ha essenzialmente prestazioni O (1) mentre uno stato di commutazione può avere O (1) o O (log (n)) a seconda se il compilatore utilizza un commutatore di tabelle o un commutatore di ricerca.Prestazioni dichiarazione HashMap vs Switch

Comprensibilmente, se un'istruzione switch è scritto come tale,

switch (int) { 
    case 1: 
    case 2: 
    case 3: 
    case 4: 
    default: 
} 

allora sarebbe utilizzare un tableswitch e chiaramente hanno un vantaggio di prestazioni nel corso di un HashMap standard. Ma cosa succede se l'istruzione switch è scarsa? Questi sarebbero due esempi che vorrei confrontare:

HashMap<Integer, String> example = new HashMap<Integer, String>() {{ 
     put(1, "a"); 
     put(10, "b"); 
     put(100, "c"); 
     put(1000, "d"); 
}}; 

.

switch (int) { 
    case 1: 
     return "a"; 
    case 10: 
     return "b"; 
    case 100: 
     return "c"; 
    case 1000: 
     return "d"; 
    default: 
     return null; 
} 

Cosa fornirebbe più throughput, un lookupswitch o HashMap? Il sovraccarico di HashMap offre un vantaggio all'inizio della commutazione, ma alla fine si assottiglia quando aumenta il numero di casi/voci?

Modifica: Ho provato alcuni benchmark utilizzando JMH, qui vengono utilizzati i miei risultati e il codice. https://gist.github.com/mooman219/bebbdc047889c7cfe612 Come avete detto voi, la dichiarazione del lookup switch ha sovraperformato la HashTable. Mi sto ancora chiedendo perché, comunque.

+1

Come quasi tutte le domande sulle prestazioni: è necessario misurarlo. http://stackoverflow.com/q/504103/139010 Attendo con ansia i tuoi risultati ':' –

+1

Una buona risposta di default è quella di dirti di misurare la differenza ... Mi aspetto che l'istruzione switch sia più veloce, perché dovrebbe ammontare a meno istruzioni. Con C e GCC, uno switch viene implementato come se/elseif-chains, jump tables o cosa no a seconda del contesto (ad es. Quanti casi nell'interruttore, indicizzazione, ecc.) –

+1

Oltre a una complessità molto minore, il meccanismo del commutatore di ricerca ha l'importante vantaggio della località di riferimento. L'hashmap deve 1. dereferenziare la chiave Integer; 2. dereferenziare l'array di benne; 3. dereferenziare l'istanza del nodo nell'array all'indice derivato da 1; 4. dereferenziare la chiave Integer del Nodo per assicurarsi che sia uguale alla chiave richiesta; 5. infine, dereferenziare il valore di ritorno dal nodo. –

risposta

18

Dipende da un sacco di cose:

  1. Se ci sono alcuni articoli/oggetti fissi. Utilizzo dell'interruttore (caso peggiore O (n))

  2. Se ci sono molti articoli O si desidera aggiungere elementi futuri senza modificare molto codice ---> Utilizzo di hash-map (il tempo di accesso è considerato come tempo costante)

  3. Per il tuo caso. Non dovresti preoccuparti delle prestazioni perché il consumo di tempo per entrambi i casi è molto basso. Concentrati solo sulla leggibilità/manutenibilità del tuo codice.

+0

Anche la lunghezza della chiave è pertinente. – OldCurmudgeon

+0

Perché molti articoli sono dannosi per l'istruzione switch? Ho sentito che il compilatore fa l'ottimizzazione e l'albero binario nelle dichiarazioni switch per noi. – shuva

0

Nel tuo caso, dal momento che si sta utilizzando una chiave Integer per il vostro HashMap e una pianura 'int' per il vostro switch dichiarazione, la migliore implementazione di eseguire sarà la switch economico a meno che il numero di passaggi attraverso questa sezione di il codice è molto alto (decine o centinaia di migliaia).