Jeśli uruchomisz następujące rozwiązania w 64-bitowej wersji HotSpot Java 7.Czy istnieje przyczyna Object.hashCode() jest 31-bitowy?
int countTopBit = 0, countLowestBit = 0;
for (int i = 0; i < 100000000; i++) {
int h = new Object().hashCode();
if (h < 0)
countTopBit++;
if ((h & 1) == 1)
countLowestBit++;
}
System.out.println("The count of negative hashCodes was " + countTopBit + ", the count of odd hashCodes was " + countLowestBit);
można uzyskać wynik jak
The count of negative hashCodes was 0, the count of odd hashCodes was 49994232
Zastanawiałem się, czy to oznacza, że tylko naprawdę Object.hashCode()
jest 31-bitowym i dlaczego to może być tak?
Nie jest tak, że górny bit nie jest używany. Od źródła do HashMap
257 /**
258 * Applies a supplemental hash function to a given hashCode, which
259 * defends against poor quality hash functions. This is critical
260 * because HashMap uses power-of-two length hash tables, that
261 * otherwise encounter collisions for hashCodes that do not differ
262 * in lower bits. Note: Null keys always map to hash 0, thus index 0.
263 */
264 static int hash(int h) {
265 // This function ensures that hashCodes that differ only by
266 // constant multiples at each bit position have a bounded
267 // number of collisions (approximately 8 at default load factor).
268 h ^= (h >>> 20)^(h >>> 12);
269 return h^(h >>> 7)^(h >>> 4);
270 }
To może być optymalizacja. Tabele skrótu często przyjmują kod skrótu, modyfikują liczbę segmentów, ale muszą najpierw maskować górny bit, aby uniknąć ujemnego indeksu. Być może jest to uniknięcie tego kroku później? – templatetypedef
@templatetypedef Zastanawiam się, może to być przypadek, ale podejrzewam, że Object.hashCode() nie jest używany w kolekcjach Hash, które często są zwykle overriden z 32-bitowym hashCode(). Również HashMap mutuje surowy kod haszujący, więc używany jest bit górny. –
@templatetypedef: ale co z nadpisaniami użytkowników, które tego nie robią? Tabela mieszania wciąż musi radzić sobie z tym –