mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8266097: Better hashing support
Reviewed-by: chegar, dfuchs, ahgross, smarks, rhalade
This commit is contained in:
parent
3a7b663b6f
commit
dd199ee063
2 changed files with 38 additions and 19 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,6 +27,7 @@ package java.util;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InvalidObjectException;
|
import java.io.InvalidObjectException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
@ -1504,23 +1505,28 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||||
* @throws IOException if an I/O error occurs
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
@java.io.Serial
|
@java.io.Serial
|
||||||
private void readObject(java.io.ObjectInputStream s)
|
private void readObject(ObjectInputStream s)
|
||||||
throws IOException, ClassNotFoundException {
|
throws IOException, ClassNotFoundException {
|
||||||
// Read in the threshold (ignored), loadfactor, and any hidden stuff
|
|
||||||
s.defaultReadObject();
|
ObjectInputStream.GetField fields = s.readFields();
|
||||||
|
|
||||||
|
// Read loadFactor (ignore threshold)
|
||||||
|
float lf = fields.get("loadFactor", 0.75f);
|
||||||
|
if (lf <= 0 || Float.isNaN(lf))
|
||||||
|
throw new InvalidObjectException("Illegal load factor: " + lf);
|
||||||
|
|
||||||
|
lf = Math.min(Math.max(0.25f, lf), 4.0f);
|
||||||
|
HashMap.UnsafeHolder.putLoadFactor(this, lf);
|
||||||
|
|
||||||
reinitialize();
|
reinitialize();
|
||||||
if (loadFactor <= 0 || Float.isNaN(loadFactor))
|
|
||||||
throw new InvalidObjectException("Illegal load factor: " +
|
|
||||||
loadFactor);
|
|
||||||
s.readInt(); // Read and ignore number of buckets
|
s.readInt(); // Read and ignore number of buckets
|
||||||
int mappings = s.readInt(); // Read number of mappings (size)
|
int mappings = s.readInt(); // Read number of mappings (size)
|
||||||
if (mappings < 0)
|
if (mappings < 0) {
|
||||||
throw new InvalidObjectException("Illegal mappings count: " +
|
throw new InvalidObjectException("Illegal mappings count: " + mappings);
|
||||||
mappings);
|
} else if (mappings == 0) {
|
||||||
else if (mappings > 0) { // (if zero, use defaults)
|
// use defaults
|
||||||
// Size the table using given load factor only if within
|
} else if (mappings > 0) {
|
||||||
// range of 0.25...4.0
|
|
||||||
float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
|
|
||||||
float fc = (float)mappings / lf + 1.0f;
|
float fc = (float)mappings / lf + 1.0f;
|
||||||
int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
|
int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
|
||||||
DEFAULT_INITIAL_CAPACITY :
|
DEFAULT_INITIAL_CAPACITY :
|
||||||
|
@ -1549,6 +1555,18 @@ public class HashMap<K,V> extends AbstractMap<K,V>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support for resetting final field during deserializing
|
||||||
|
private static final class UnsafeHolder {
|
||||||
|
private UnsafeHolder() { throw new InternalError(); }
|
||||||
|
private static final jdk.internal.misc.Unsafe unsafe
|
||||||
|
= jdk.internal.misc.Unsafe.getUnsafe();
|
||||||
|
private static final long LF_OFFSET
|
||||||
|
= unsafe.objectFieldOffset(HashMap.class, "loadFactor");
|
||||||
|
static void putLoadFactor(HashMap<?, ?> map, float lf) {
|
||||||
|
unsafe.putFloat(map, LF_OFFSET, lf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
// iterators
|
// iterators
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -297,8 +297,8 @@ public class HashSet<E>
|
||||||
@java.io.Serial
|
@java.io.Serial
|
||||||
private void readObject(java.io.ObjectInputStream s)
|
private void readObject(java.io.ObjectInputStream s)
|
||||||
throws java.io.IOException, ClassNotFoundException {
|
throws java.io.IOException, ClassNotFoundException {
|
||||||
// Read in any hidden serialization magic
|
// Consume and ignore stream fields (currently zero).
|
||||||
s.defaultReadObject();
|
s.readFields();
|
||||||
|
|
||||||
// Read capacity and verify non-negative.
|
// Read capacity and verify non-negative.
|
||||||
int capacity = s.readInt();
|
int capacity = s.readInt();
|
||||||
|
@ -313,12 +313,13 @@ public class HashSet<E>
|
||||||
throw new InvalidObjectException("Illegal load factor: " +
|
throw new InvalidObjectException("Illegal load factor: " +
|
||||||
loadFactor);
|
loadFactor);
|
||||||
}
|
}
|
||||||
|
// Clamp load factor to range of 0.25...4.0.
|
||||||
|
loadFactor = Math.min(Math.max(0.25f, loadFactor), 4.0f);
|
||||||
|
|
||||||
// Read size and verify non-negative.
|
// Read size and verify non-negative.
|
||||||
int size = s.readInt();
|
int size = s.readInt();
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
throw new InvalidObjectException("Illegal size: " +
|
throw new InvalidObjectException("Illegal size: " + size);
|
||||||
size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the capacity according to the size and load factor ensuring that
|
// Set the capacity according to the size and load factor ensuring that
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue