2012-03-19 11 views
6

Mi chiedo se l'implementazione predefinita di Java Hashtable#hashCode() sia interrotta quando lo Hashtable contiene solo voci con chiavi e valori identici per coppia.Implementazione hashCode() di Java Hashtable # rotta?

Si veda ad esempio la seguente applicazione:

public class HashtableHash { 
    public static void main(final String[] args) { 
     final Hashtable<String, String> ht = new Hashtable<String, String>(); 

     final int h1 = ht.hashCode(); 
     System.out.println(h1); // output is 0 

     ht.put("Test", "Test"); 

     final int h2 = ht.hashCode(); 
     System.out.println(h2); // output is 0 ?!? 

     // Hashtable#hashCode() uses this algorithm to calculate hash code 
     // of every element: 
     // 
     // h += e.key.hashCode()^e.value.hashCode() 
     // 
     // The result of XOR on identical hash codes is always 0 
     // (because all bits are equal) 

     ht.put("Test2", "Hello world"); 

     final int h3 = ht.hashCode(); 
     System.out.println(h3); // output is some hash code 
    } 
} 

il codice hash per un Hashtable vuota è 0. Dopo una voce con la chiave e il valore "Test""Test" è stato aggiunto al Hastable il codice hash ancora è 0.

il problema è che nel metodo di Hashtable hashCode() il codice hash di ogni voce viene calcolato e aggiunto al codice hash come segue

Tuttavia XOR su codici hash identici (come nel caso di stringhe identiche) è sempre 0. Pertanto, le voci con chiavi e valori identici non fanno parte del codice hash di Hashtable.

Questa implementazione è imho interrotta perché l'Hashtable è effettivamente cambiato. Non dovrebbe essere importante se la chiave e il valore sono identici.

+2

Mi chiedo perché questo è stato downvoted perché è una domanda legittima e potrebbe salvare alcuni problemi. Ho cercato ore per trovare un bug causato da questo comportamento. –

+2

* non è possibile * fare affidamento su un hashcode diverso solo perché l'oggetto è diverso. Diresti che l'hashCode è rotto anche se aggiungo due oggetti completamente diversi e anche l'hashCode rimane lo stesso? In tal caso, ogni possibile implementazione di hashcode viene interrotta se l'universo di possibili oggetti è maggiore di 2^32 .. – Voo

+0

È più un'osservazione che una domanda. (Sebbene non sia il mio downvote.) –

risposta

6

Dalla documentazione su hashCode;

È non richiesto che se due oggetti sono uguali secondo il metodo equals (java.lang.Object), poi chiama il metodo hashCode su ciascuno dei due oggetti devono produrre risultati interi distinti. Tuttavia, il programmatore deve essere consapevole del fatto che la produzione di distinti risultati interi per oggetti non uguali può migliorare le prestazioni degli hash .

In altre parole, cattiva implementazione - forse. Rotto - non secondo le specifiche.

5

Non è rotto, funziona come progettato e pubblicizzato. Il codice hash di due uguali Map s non richiede che i due Map siano uguali.

1

L'unico requisito di è che se due oggetti sono uguali, i loro codici hash devono essere uguali. Quindi

public int hashCode() { 
    return 123; 
} 

è perfettamente valido, anche se non ottimale.