Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8186958: Need method to create pre-sized HashMap #7928

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1461683
8186958: Need method to create pre-sized HashMap
XenoAmess Mar 23, 2022
68787ac
fix javadoc's @return
XenoAmess Mar 24, 2022
2b294b3
move the static functions to map classes themselves.
XenoAmess Mar 24, 2022
5457e6c
use jmh Blackhole
XenoAmess Mar 24, 2022
4cf926d
delete a space.
XenoAmess Mar 24, 2022
dadde82
refine javadoc about default load factor
XenoAmess Mar 24, 2022
aea7edf
refine javadoc; refine implement when expectedSize < 0
XenoAmess Mar 24, 2022
e5bc200
update jmh
XenoAmess Mar 24, 2022
7a1f3b0
update codes
XenoAmess Mar 30, 2022
d4147bc
update usages of HashMap
XenoAmess Apr 2, 2022
ec0b08c
update usages of LinkedHashMap
XenoAmess Apr 2, 2022
796975b
revert changes in jdk.compile
XenoAmess Apr 2, 2022
e548cd6
refine javadoc for LinkedHashMap#newLinkedHashMap
XenoAmess Apr 6, 2022
4769b87
drop CalculateHashMapCapacityTestJMH
XenoAmess Apr 6, 2022
b973ee5
use (double) DEFAULT_LOAD_FACTOR instead of 0.75
XenoAmess Apr 6, 2022
bdf47f3
variable nameToReferenceSize rename to moduleCount
XenoAmess Apr 10, 2022
7adc89c
Merge branch 'master' into fix_8186958
XenoAmess Apr 10, 2022
5801dc7
Minor adjustment to test cases of WhiteBoxResizeTest
stuart-marks Apr 13, 2022
2f6f8f4
Add test cases for static factory methods.
stuart-marks Apr 13, 2022
ab8fbb8
Add apiNote to appropriate constructors of HM, LHM, and WHM.
stuart-marks Apr 13, 2022
2f5617b
revert changes in:
XenoAmess Apr 13, 2022
4476c76
Copyright latest year to 2022
XenoAmess Apr 13, 2022
d110ecf
update LastModified
XenoAmess Apr 13, 2022
5603f19
fix usage in XSAttributeChecker
XenoAmess Apr 14, 2022
5b437da
revert changes on ProcessEnvironment
XenoAmess Apr 14, 2022
71b7dba
add `@LastModified: Apr 2022` to DocumentCache
XenoAmess Apr 14, 2022
95e22f2
java.xml.crypto's usage downgrade grammar to 1.8
XenoAmess Apr 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -570,7 +570,7 @@ public Map<String, Integer> getDisplayNames(String calendarType,
String[] names = getCalendarDisplayStrings(locale.toLanguageTag(),
field, style);
if (names != null) {
map = new HashMap<>((int)Math.ceil(names.length / 0.75));
map = HashMap.newHashMap(names.length);
for (int value = 0; value < names.length; value++) {
if (names[value] != null) {
map.put(names[value], value);
Expand Down
5 changes: 2 additions & 3 deletions src/java.base/share/classes/java/lang/Character.java
Original file line number Diff line number Diff line change
Expand Up @@ -744,8 +744,7 @@ public static final class UnicodeBlock extends Subset {
* 0.75 - the default load factor of HashMap
*/
private static final int NUM_ENTITIES = 737;
private static Map<String, UnicodeBlock> map =
new HashMap<>((int)(NUM_ENTITIES / 0.75f + 1.0f));
private static Map<String, UnicodeBlock> map = HashMap.newHashMap(NUM_ENTITIES);

/**
* Creates a UnicodeBlock with the given identifier name.
Expand Down Expand Up @@ -8572,7 +8571,7 @@ public static enum UnicodeScript {

private static final HashMap<String, Character.UnicodeScript> aliases;
static {
aliases = new HashMap<>((int)(162 / 0.75f + 1.0f));
aliases = HashMap.newHashMap(162);
aliases.put("ADLM", ADLAM);
aliases.put("AGHB", CAUCASIAN_ALBANIAN);
aliases.put("AHOM", AHOM);
Expand Down
6 changes: 3 additions & 3 deletions src/java.base/share/classes/java/lang/Class.java
Original file line number Diff line number Diff line change
Expand Up @@ -3910,7 +3910,7 @@ Map<String, T> enumConstantDirectory() {
if (universe == null)
throw new IllegalArgumentException(
getName() + " is not an enum class");
directory = new HashMap<>((int)(universe.length / 0.75f) + 1);
directory = HashMap.newHashMap(universe.length);
for (T constant : universe) {
directory.put(((Enum<?>)constant).name(), constant);
}
Expand Down Expand Up @@ -4125,10 +4125,10 @@ private AnnotationData createAnnotationData(int classRedefinedCount) {
Class<? extends Annotation> annotationClass = e.getKey();
if (AnnotationType.getInstance(annotationClass).isInherited()) {
if (annotations == null) { // lazy construction
annotations = new LinkedHashMap<>((Math.max(
annotations = LinkedHashMap.newLinkedHashMap(Math.max(
declaredAnnotations.size(),
Math.min(12, declaredAnnotations.size() + superAnnotations.size())
) * 4 + 2) / 3
)
);
}
annotations.put(annotationClass, e.getValue());
Expand Down
7 changes: 3 additions & 4 deletions src/java.base/share/classes/java/lang/Module.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -980,7 +980,7 @@ void implAddOpensToAllUnnamed(Set<String> concealedPkgs, Set<String> exportedPkg
// the packages to all unnamed modules.
Map<String, Set<Module>> openPackages = this.openPackages;
if (openPackages == null) {
openPackages = new HashMap<>((4 * (concealedPkgs.size() + exportedPkgs.size()) / 3) + 1);
openPackages = HashMap.newHashMap(concealedPkgs.size() + exportedPkgs.size());
} else {
openPackages = new HashMap<>(openPackages);
}
Expand Down Expand Up @@ -1133,8 +1133,7 @@ static Map<String, Module> defineModules(Configuration cf,
boolean isBootLayer = (ModuleLayer.boot() == null);

int numModules = cf.modules().size();
int cap = (int)(numModules / 0.75f + 1.0f);
Map<String, Module> nameToModule = new HashMap<>(cap);
Map<String, Module> nameToModule = HashMap.newHashMap(numModules);

// to avoid repeated lookups and reduce iteration overhead, we create
// arrays holding correlated information about each module.
Expand Down
2 changes: 1 addition & 1 deletion src/java.base/share/classes/java/lang/Thread.java
Original file line number Diff line number Diff line change
Expand Up @@ -1655,7 +1655,7 @@ public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
// Get a snapshot of the list of all threads
Thread[] threads = getThreads();
StackTraceElement[][] traces = dumpThreads(threads);
Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
Map<Thread, StackTraceElement[]> m = HashMap.newHashMap(threads.length);
for (int i = 0; i < threads.length; i++) {
StackTraceElement[] stackTrace = traces[i];
if (stackTrace != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -290,7 +290,7 @@ static MethodHandle makePairwiseConvertByEditor(MethodHandle target, MethodType
BoundMethodHandle mh = target.rebind();

// Match each unique conversion to the positions at which it is to be applied
var convSpecMap = new HashMap<Object, int[]>(((4 * convCount) / 3) + 1);
HashMap<Object, int[]> convSpecMap = HashMap.newHashMap(convCount);
for (int i = 0; i < convSpecs.length - MH_RECEIVER_OFFSET; i++) {
Object convSpec = convSpecs[i];
if (convSpec == null) continue;
Expand Down
11 changes: 5 additions & 6 deletions src/java.base/share/classes/java/lang/module/Resolver.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -498,12 +498,11 @@ private void checkHashes() {
*/
private Map<ResolvedModule, Set<ResolvedModule>> makeGraph(Configuration cf) {

// initial capacity of maps to avoid resizing
int capacity = 1 + (4 * nameToReference.size())/ 3;
int moduleCount = nameToReference.size();

// the "reads" graph starts as a module dependence graph and
// is iteratively updated to be the readability graph
Map<ResolvedModule, Set<ResolvedModule>> g1 = new HashMap<>(capacity);
Map<ResolvedModule, Set<ResolvedModule>> g1 = HashMap.newHashMap(moduleCount);

// the "requires transitive" graph, contains requires transitive edges only
Map<ResolvedModule, Set<ResolvedModule>> g2;
Expand All @@ -512,7 +511,7 @@ private Map<ResolvedModule, Set<ResolvedModule>> makeGraph(Configuration cf) {
// as there may be selected modules that have a dependency on modules in
// the parent configuration.
if (ModuleLayer.boot() == null) {
g2 = new HashMap<>(capacity);
g2 = HashMap.newHashMap(moduleCount);
} else {
g2 = parents.stream()
.flatMap(Configuration::configurations)
Expand All @@ -539,7 +538,7 @@ private Map<ResolvedModule, Set<ResolvedModule>> makeGraph(Configuration cf) {

// populate g1 and g2 with the dependences from the selected modules

Map<String, ResolvedModule> nameToResolved = new HashMap<>(capacity);
Map<String, ResolvedModule> nameToResolved = HashMap.newHashMap(moduleCount);

for (ModuleReference mref : nameToReference.values()) {
ModuleDescriptor descriptor = mref.descriptor();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -245,7 +245,7 @@ private void readObject(ObjectInputStream ois)
} else if (size < 0) {
throw new IOException("size cannot be negative");
} else {
extensions = new HashMap<>(size > 20 ? 20 : size);
extensions = HashMap.newHashMap(size > 20 ? 20 : size);
}

// Read in the extensions and put the mappings in the extensions map
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -197,7 +197,7 @@ public void setOcspResponses(Map<X509Certificate, byte[]> responses)
if (responses == null) {
this.ocspResponses = Collections.<X509Certificate, byte[]>emptyMap();
} else {
Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size());
Map<X509Certificate, byte[]> copy = HashMap.newHashMap(responses.size());
for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) {
copy.put(e.getKey(), e.getValue().clone());
}
Expand All @@ -216,7 +216,7 @@ public void setOcspResponses(Map<X509Certificate, byte[]> responses)
* Returns an empty map if no responses have been specified.
*/
public Map<X509Certificate, byte[]> getOcspResponses() {
Map<X509Certificate, byte[]> copy = new HashMap<>(ocspResponses.size());
Map<X509Certificate, byte[]> copy = HashMap.newHashMap(ocspResponses.size());
for (Map.Entry<X509Certificate, byte[]> e : ocspResponses.entrySet()) {
copy.put(e.getKey(), e.getValue().clone());
}
Expand Down
38 changes: 37 additions & 1 deletion src/java.base/share/classes/java/util/HashMap.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -433,6 +433,10 @@ static final int tableSizeFor(int cap) {
* Constructs an empty {@code HashMap} with the specified initial
* capacity and load factor.
*
* @apiNote
* To create a {@code HashMap} with an initial capacity that accommodates
* an expected number of mappings, use {@link #newHashMap(int) newHashMap}.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
Expand All @@ -455,6 +459,10 @@ public HashMap(int initialCapacity, float loadFactor) {
* Constructs an empty {@code HashMap} with the specified initial
* capacity and the default load factor (0.75).
*
* @apiNote
* To create a {@code HashMap} with an initial capacity that accommodates
* an expected number of mappings, use {@link #newHashMap(int) newHashMap}.
*
* @param initialCapacity the initial capacity.
* @throws IllegalArgumentException if the initial capacity is negative.
*/
Expand Down Expand Up @@ -2545,4 +2553,32 @@ static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
}
}

/**
* Calculate initial capacity for HashMap based classes, from expected size and default load factor (0.75).
*
* @param numMappings the expected number of mappings
* @return initial capacity for HashMap based classes.
* @since 19
*/
static int calculateHashMapCapacity(int numMappings) {
return (int) Math.ceil(numMappings / (double) DEFAULT_LOAD_FACTOR);
}

/**
* Creates a new, empty HashMap suitable for the expected number of mappings.
* The returned map uses the default load factor of 0.75, and its initial capacity is
* generally large enough so that the expected number of mappings can be added
* without resizing the map.
*
* @param numMappings the expected number of mappings
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
* @return the newly created map
* @throws IllegalArgumentException if numMappings is negative
* @since 19
*/
public static <K, V> HashMap<K, V> newHashMap(int numMappings) {
return new HashMap<>(calculateHashMapCapacity(numMappings));
}

}
4 changes: 2 additions & 2 deletions src/java.base/share/classes/java/util/HashSet.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -117,7 +117,7 @@ public HashSet() {
* @throws NullPointerException if the specified collection is null
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
map = HashMap.newHashMap(Math.max(c.size(), 12));
addAll(c);
}

Expand Down
26 changes: 25 additions & 1 deletion src/java.base/share/classes/java/util/LinkedHashMap.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -339,6 +339,10 @@ void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
* Constructs an empty insertion-ordered {@code LinkedHashMap} instance
* with the specified initial capacity and load factor.
*
* @apiNote
* To create a {@code LinkedHashMap} with an initial capacity that accommodates
* an expected number of mappings, use {@link #newLinkedHashMap(int) newLinkedHashMap}.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
Expand All @@ -353,6 +357,10 @@ public LinkedHashMap(int initialCapacity, float loadFactor) {
* Constructs an empty insertion-ordered {@code LinkedHashMap} instance
* with the specified initial capacity and a default load factor (0.75).
*
* @apiNote
* To create a {@code LinkedHashMap} with an initial capacity that accommodates
* an expected number of mappings, use {@link #newLinkedHashMap(int) newLinkedHashMap}.
*
* @param initialCapacity the initial capacity
* @throws IllegalArgumentException if the initial capacity is negative
*/
Expand Down Expand Up @@ -788,5 +796,21 @@ final class LinkedEntryIterator extends LinkedHashIterator
public final Map.Entry<K,V> next() { return nextNode(); }
}

/**
* Creates a new, empty, insertion-ordered LinkedHashMap suitable for the expected number of mappings.
* The returned map uses the default load factor of 0.75, and its initial capacity is
* generally large enough so that the expected number of mappings can be added
* without resizing the map.
*
* @param numMappings the expected number of mappings
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
* @return the newly created map
* @throws IllegalArgumentException if numMappings is negative
* @since 19
*/
public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(int numMappings) {
return new LinkedHashMap<>(HashMap.calculateHashMapCapacity(numMappings));
}

}
4 changes: 2 additions & 2 deletions src/java.base/share/classes/java/util/ListResourceBundle.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -193,7 +193,7 @@ private synchronized void loadLookup() {
return;

Object[][] contents = getContents();
HashMap<String,Object> temp = new HashMap<>(contents.length);
HashMap<String,Object> temp = HashMap.newHashMap(contents.length);
for (Object[] content : contents) {
// key must be non-null String, value must be non-null
String key = (String) content[0];
Expand Down
27 changes: 26 additions & 1 deletion src/java.base/share/classes/java/util/WeakHashMap.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -198,6 +198,10 @@ private Entry<K,V>[] newTable(int n) {
* Constructs a new, empty {@code WeakHashMap} with the given initial
* capacity and the given load factor.
*
* @apiNote
* To create a {@code WeakHashMap} with an initial capacity that accommodates
* an expected number of mappings, use {@link #newWeakHashMap(int) newWeakHashMap}.
*
* @param initialCapacity The initial capacity of the {@code WeakHashMap}
* @param loadFactor The load factor of the {@code WeakHashMap}
* @throws IllegalArgumentException if the initial capacity is negative,
Expand All @@ -223,6 +227,10 @@ public WeakHashMap(int initialCapacity, float loadFactor) {
* Constructs a new, empty {@code WeakHashMap} with the given initial
* capacity and the default load factor (0.75).
*
* @apiNote
* To create a {@code WeakHashMap} with an initial capacity that accommodates
* an expected number of mappings, use {@link #newWeakHashMap(int) newWeakHashMap}.
*
* @param initialCapacity The initial capacity of the {@code WeakHashMap}
* @throws IllegalArgumentException if the initial capacity is negative
*/
Expand Down Expand Up @@ -1335,4 +1343,21 @@ public int characteristics() {
}
}

/**
* Creates a new, empty WeakHashMap suitable for the expected number of mappings.
* The returned map uses the default load factor of 0.75, and its initial capacity is
* generally large enough so that the expected number of mappings can be added
* without resizing the map.
*
* @param numMappings the expected number of mappings
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
* @return the newly created map
* @throws IllegalArgumentException if numMappings is negative
* @since 19
*/
public static <K, V> WeakHashMap<K, V> newWeakHashMap(int numMappings) {
return new WeakHashMap<>(HashMap.calculateHashMapCapacity(numMappings));
}

}
Loading