Alcuni principali classi JVM (come ad esempio String o List implementations) implementano equivale restituendo Σ 31^n * field_n.hashCode()
per ogni field_n
che è rilevante per il metodo equals
. Inoltre, questo approccio è raccomandato da Joshua Bloch in Java efficace (articolo 9).hashCode strategie di attuazione
Tuttavia, altre classi come Map.Entry
implementations seguono regole diverse. Ad esempio, la documentazione Map.Entry afferma che il codice hash di un Map.Entry
dovrebbe essere
(e.getKey()==null ? 0 : e.getKey().hashCode())^
(e.getValue()==null ? 0 : e.getValue().hashCode())
Questo a volte può essere poco pratico da utilizzare in tabelle hash, poiché:
- il codice hash di tutte le voci che hanno la stessa chiave e il valore è 0,
- due voci e1 ed e2 in modo che e1.key = e2.value e e1.value = e2.key abbiano lo stesso codice hash.
Perché Java ha scelto questa specifica di implementazione per Map.Entry
hashCode anziché, ad esempio, 31 * (e.getKey()==null ? 0 : e.getKey().hashCode()) + (e.getValue()==null ? 0 : e.getValue().hashCode())
?
Edit 1:
Per aiutare a capire il problema, ecco un esempio di codice utile in cui il risultato ha prestazioni molto povera a causa di collisioni hash se molte voci hanno lo stesso valore chiave e.
Questo metodo calcola le frequenze delle voci di diverse mappe (utilizzando il Multiset di Guava).
public static <K, V> Multiset<Map.Entry<K, V>> computeEntryCounts(
Iterable<Map<K, V>> maps) {
ImmutableMultiset.Builder<Map.Entry<K, V>> result = ImmutableMultiset.builder();
for (Map<K, V> map : maps) {
for (Map.Entry<K, V> entry : map.entrySet()) {
result.add(entry);
}
}
return result.build();
}
L'implementazione non ha alcun effetto sull'output perché la chiave e il valore sono ** null **. Inoltre, non ci sono più di ** una ** voce con una chiave in una mappa in Java, una chiave si verifica solo ** una volta ** in qualsiasi implementazione della mappa. –
Lo so, stavo dando per scontato che le chiavi di HashMap siano istanze di Map.Entry. Ciò può accadere se si desidera calcolare il conteggio totale per ciascuna voce di valori-chiave su più mappe. – jpountz
Non riesco a vedere come questo influenzerà questo caso, a meno che non si desideri posizionare tutte le Map.Entry da tutte le mappe all'interno di una singola mappa per contarle, ma ciò sarebbe chiaramente sbagliato. –