Algunas clases de JVM importantes (tales como String o List implementations) implementar equals devolviendo Σ 31^n * field_n.hashCode()
para cada field_n
que es relevante para el método equals
. Además, este enfoque es recomendado por Joshua Bloch en Java efectivo (elemento 9).estrategias de aplicación hashCode
Sin embargo, otras clases como Map.Entry
implementations siguen reglas diferentes. Por ejemplo, la documentación Map.Entry establece que el código hash de un Map.Entry
debe ser
(e.getKey()==null ? 0 : e.getKey().hashCode())^
(e.getValue()==null ? 0 : e.getValue().hashCode())
Esto a veces puede no ser práctico utilizar en tablas hash, ya que:
- el código hash de todas las entradas que tienen la misma clave y valor es 0,
- dos entradas e1 y e2 para que e1.key = e2.value y e1.value = e2.key tengan el mismo código hash.
¿Por qué elegir esta especificación Java aplicación de Map.Entry
hashCode en lugar de, por ejemplo, 31 * (e.getKey()==null ? 0 : e.getKey().hashCode()) + (e.getValue()==null ? 0 : e.getValue().hashCode())
?
Edición 1:
para ayudar a determinar el problema, aquí es un ejemplo de código útil cuando el resultado tiene un rendimiento muy pobre debido a las colisiones de hash si muchas entradas tienen el mismo valor de clave y.
Este método calcula las frecuencias de las entradas de diferentes mapas (utilizando Multiset de 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();
}
Su implementación no afecta la salida de la clave y el valor siendo ** nulo **. Además, no hay más de ** una ** entrada con una clave en un Mapa en Java, una clave solo ocurre ** una vez ** en cualquier implementación de Mapa. –
Lo sé, estaba asumiendo que las claves de HashMap son instancias de Map.Entry. Esto puede suceder si desea calcular el recuento total de cada entrada de clave-valor en varios mapas. – jpountz
No puedo ver cómo va a afectar esto a este caso, a menos que desee colocar todo Map.Entry de todos los mapas dentro de un solo mapa para contarlos, pero esto sería claramente incorrecto. –