Avoid resizing of fixed-size HashSet/LinkedHashSet variants
Add helpers to CollectionUtils for building HashSets and LinkedHashSets that can hold an expected number of elements without needing to resize/rehash. Closes gh-32291
This commit is contained in:
committed by
Sam Brannen
parent
6383a0d7ca
commit
e1a32d4ba9
@@ -18,7 +18,6 @@ package org.springframework.core.convert.support;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -26,6 +25,7 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Convert an Object to {@code java.util.Optional<T>} if necessary using the
|
||||
@@ -48,7 +48,7 @@ final class ObjectToOptionalConverter implements ConditionalGenericConverter {
|
||||
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
Set<ConvertiblePair> convertibleTypes = new LinkedHashSet<>(4);
|
||||
Set<ConvertiblePair> convertibleTypes = CollectionUtils.newLinkedHashSet(3);
|
||||
convertibleTypes.add(new ConvertiblePair(Collection.class, Optional.class));
|
||||
convertibleTypes.add(new ConvertiblePair(Object[].class, Optional.class));
|
||||
convertibleTypes.add(new ConvertiblePair(Object.class, Optional.class));
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -89,7 +90,7 @@ public class CompositePropertySource extends EnumerablePropertySource<Object> {
|
||||
namesList.add(names);
|
||||
total += names.length;
|
||||
}
|
||||
Set<String> allNames = new LinkedHashSet<>(total);
|
||||
Set<String> allNames = CollectionUtils.newLinkedHashSet(total);
|
||||
namesList.forEach(names -> Collections.addAll(allNames, names));
|
||||
return StringUtils.toStringArray(allNames);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.nio.channels.WritableByteChannel;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -54,6 +53,7 @@ import reactor.util.context.Context;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Utility class for working with {@link DataBuffer DataBuffers}.
|
||||
@@ -382,7 +382,7 @@ public abstract class DataBufferUtils {
|
||||
|
||||
private static Set<OpenOption> checkWriteOptions(OpenOption[] options) {
|
||||
int length = options.length;
|
||||
Set<OpenOption> result = new HashSet<>(length + 3);
|
||||
Set<OpenOption> result = CollectionUtils.newHashSet(length > 0 ? length : 2);
|
||||
if (length == 0) {
|
||||
result.add(StandardOpenOption.CREATE);
|
||||
result.add(StandardOpenOption.TRUNCATE_EXISTING);
|
||||
|
||||
@@ -22,8 +22,10 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
@@ -85,7 +87,7 @@ public abstract class CollectionUtils {
|
||||
* @see #newLinkedHashMap(int)
|
||||
*/
|
||||
public static <K, V> HashMap<K, V> newHashMap(int expectedSize) {
|
||||
return new HashMap<>(computeMapInitialCapacity(expectedSize), DEFAULT_LOAD_FACTOR);
|
||||
return new HashMap<>(computeInitialCapacity(expectedSize), DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,10 +104,34 @@ public abstract class CollectionUtils {
|
||||
* @see #newHashMap(int)
|
||||
*/
|
||||
public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(int expectedSize) {
|
||||
return new LinkedHashMap<>(computeMapInitialCapacity(expectedSize), DEFAULT_LOAD_FACTOR);
|
||||
return new LinkedHashMap<>(computeInitialCapacity(expectedSize), DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
private static int computeMapInitialCapacity(int expectedSize) {
|
||||
/**
|
||||
* Instantiate a new {@link HashSet} with an initial capacity
|
||||
* that can accommodate the specified number of elements without
|
||||
* any immediate resize/rehash operations to be expected.
|
||||
* @param expectedSize the expected number of elements (with a corresponding
|
||||
* capacity to be derived so that no resize/rehash operations are needed)
|
||||
* @see #newLinkedHashSet(int)
|
||||
*/
|
||||
public static <E> HashSet<E> newHashSet(int expectedSize) {
|
||||
return new HashSet<>(computeInitialCapacity(expectedSize), DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new {@link LinkedHashSet} with an initial capacity
|
||||
* that can accommodate the specified number of elements without
|
||||
* any immediate resize/rehash operations to be expected.
|
||||
* @param expectedSize the expected number of elements (with a corresponding
|
||||
* capacity to be derived so that no resize/rehash operations are needed)
|
||||
* @see #newHashSet(int)
|
||||
*/
|
||||
public static <E> LinkedHashSet<E> newLinkedHashSet(int expectedSize) {
|
||||
return new LinkedHashSet<>(computeInitialCapacity(expectedSize), DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
private static int computeInitialCapacity(int expectedSize) {
|
||||
return (int) Math.ceil(expectedSize / (double) DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user