Skip to content

Commit

Permalink
8186958: Need method to create pre-sized HashMap
Browse files Browse the repository at this point in the history
Reviewed-by: chegar, naoto, joehw, lancea, wetmore, smarks
  • Loading branch information
XenoAmess authored and Stuart Marks committed Apr 19, 2022
1 parent 41fc078 commit 87faa85
Show file tree
Hide file tree
Showing 30 changed files with 208 additions and 73 deletions.
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

1 comment on commit 87faa85

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.