Skip to content

Commit e1a32d4

Browse files
kilinksbrannen
authored andcommitted
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
1 parent 6383a0d commit e1a32d4

File tree

47 files changed

+114
-75
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+114
-75
lines changed

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
import org.springframework.lang.Nullable;
8989
import org.springframework.util.Assert;
9090
import org.springframework.util.ClassUtils;
91+
import org.springframework.util.CollectionUtils;
9192
import org.springframework.util.ObjectUtils;
9293
import org.springframework.util.ReflectionUtils;
9394
import org.springframework.util.StringUtils;
@@ -163,7 +164,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
163164

164165
protected final Log logger = LogFactory.getLog(getClass());
165166

166-
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
167+
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = CollectionUtils.newLinkedHashSet(4);
167168

168169
private String requiredParameterName = "required";
169170

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ public LifecycleMetadata(Class<?> beanClass, Collection<LifecycleMethod> initMet
363363
}
364364

365365
public void checkInitDestroyMethods(RootBeanDefinition beanDefinition) {
366-
Set<LifecycleMethod> checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
366+
Set<LifecycleMethod> checkedInitMethods = CollectionUtils.newLinkedHashSet(this.initMethods.size());
367367
for (LifecycleMethod lifecycleMethod : this.initMethods) {
368368
String methodIdentifier = lifecycleMethod.getIdentifier();
369369
if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
@@ -374,7 +374,7 @@ public void checkInitDestroyMethods(RootBeanDefinition beanDefinition) {
374374
}
375375
}
376376
}
377-
Set<LifecycleMethod> checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
377+
Set<LifecycleMethod> checkedDestroyMethods = CollectionUtils.newLinkedHashSet(this.destroyMethods.size());
378378
for (LifecycleMethod lifecycleMethod : this.destroyMethods) {
379379
String methodIdentifier = lifecycleMethod.getIdentifier();
380380
if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323
import java.lang.reflect.Method;
2424
import java.util.Collection;
2525
import java.util.Collections;
26-
import java.util.LinkedHashSet;
2726
import java.util.Set;
2827

2928
import org.springframework.beans.MutablePropertyValues;
3029
import org.springframework.beans.PropertyValues;
3130
import org.springframework.beans.factory.support.RootBeanDefinition;
3231
import org.springframework.lang.Nullable;
32+
import org.springframework.util.CollectionUtils;
3333
import org.springframework.util.ReflectionUtils;
3434

3535
/**
@@ -124,7 +124,7 @@ public void checkConfigMembers(RootBeanDefinition beanDefinition) {
124124
this.checkedElements = Collections.emptySet();
125125
}
126126
else {
127-
Set<InjectedElement> checkedElements = new LinkedHashSet<>((this.injectedElements.size() * 4 / 3) + 1);
127+
Set<InjectedElement> checkedElements = CollectionUtils.newLinkedHashSet(this.injectedElements.size());
128128
for (InjectedElement element : this.injectedElements) {
129129
Member member = element.getMember();
130130
if (!beanDefinition.isExternallyManagedConfigMember(member)) {

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.lang.annotation.Annotation;
2020
import java.lang.reflect.AnnotatedElement;
2121
import java.lang.reflect.Method;
22-
import java.util.LinkedHashSet;
2322
import java.util.Map;
2423
import java.util.Set;
2524

@@ -40,6 +39,7 @@
4039
import org.springframework.lang.Nullable;
4140
import org.springframework.util.Assert;
4241
import org.springframework.util.ClassUtils;
42+
import org.springframework.util.CollectionUtils;
4343
import org.springframework.util.ObjectUtils;
4444

4545
/**
@@ -59,7 +59,7 @@
5959
*/
6060
public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver {
6161

62-
private final Set<Class<? extends Annotation>> qualifierTypes = new LinkedHashSet<>(2);
62+
private final Set<Class<? extends Annotation>> qualifierTypes = CollectionUtils.newLinkedHashSet(2);
6363

6464
private Class<? extends Annotation> valueAnnotationType = Value.class;
6565

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredMethodArgumentsResolver.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.lang.reflect.Method;
2020
import java.util.Arrays;
21-
import java.util.LinkedHashSet;
2221
import java.util.Set;
2322
import java.util.stream.Collectors;
2423

@@ -34,6 +33,7 @@
3433
import org.springframework.core.MethodParameter;
3534
import org.springframework.lang.Nullable;
3635
import org.springframework.util.Assert;
36+
import org.springframework.util.CollectionUtils;
3737
import org.springframework.util.ReflectionUtils;
3838
import org.springframework.util.function.ThrowingConsumer;
3939

@@ -165,7 +165,7 @@ private AutowiredArguments resolveArguments(RegisteredBean registeredBean,
165165
AutowireCapableBeanFactory autowireCapableBeanFactory = (AutowireCapableBeanFactory) beanFactory;
166166
int argumentCount = method.getParameterCount();
167167
Object[] arguments = new Object[argumentCount];
168-
Set<String> autowiredBeanNames = new LinkedHashSet<>(argumentCount);
168+
Set<String> autowiredBeanNames = CollectionUtils.newLinkedHashSet(argumentCount);
169169
TypeConverter typeConverter = beanFactory.getTypeConverter();
170170
for (int i = 0; i < argumentCount; i++) {
171171
MethodParameter parameter = new MethodParameter(method, i);

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.lang.reflect.Modifier;
2323
import java.lang.reflect.Parameter;
2424
import java.util.Arrays;
25-
import java.util.HashSet;
2625
import java.util.LinkedHashSet;
2726
import java.util.Map;
2827
import java.util.Set;
@@ -49,6 +48,7 @@
4948
import org.springframework.lang.Nullable;
5049
import org.springframework.util.Assert;
5150
import org.springframework.util.ClassUtils;
51+
import org.springframework.util.CollectionUtils;
5252
import org.springframework.util.ObjectUtils;
5353
import org.springframework.util.ReflectionUtils;
5454
import org.springframework.util.function.ThrowingBiFunction;
@@ -289,7 +289,7 @@ private ValueHolder[] resolveArgumentValues(RegisteredBean registeredBean, Execu
289289
beanFactory, registeredBean.getBeanName(), beanDefinition, beanFactory.getTypeConverter());
290290
ConstructorArgumentValues values = resolveConstructorArguments(
291291
valueResolver, beanDefinition.getConstructorArgumentValues());
292-
Set<ValueHolder> usedValueHolders = new HashSet<>(parameters.length);
292+
Set<ValueHolder> usedValueHolders = CollectionUtils.newHashSet(parameters.length);
293293
for (int i = 0; i < parameters.length; i++) {
294294
Class<?> parameterType = parameters[i].getType();
295295
String parameterName = (parameters[i].isNamePresent() ? parameters[i].getName() : null);

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/config/SetFactoryBean.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616

1717
package org.springframework.beans.factory.config;
1818

19-
import java.util.LinkedHashSet;
2019
import java.util.Set;
2120

2221
import org.springframework.beans.BeanUtils;
2322
import org.springframework.beans.TypeConverter;
2423
import org.springframework.core.ResolvableType;
2524
import org.springframework.lang.Nullable;
25+
import org.springframework.util.CollectionUtils;
2626

2727
/**
2828
* Simple factory for shared Set instances. Allows for central setup
@@ -85,7 +85,7 @@ protected Set<Object> createInstance() {
8585
result = BeanUtils.instantiateClass(this.targetSetClass);
8686
}
8787
else {
88-
result = new LinkedHashSet<>(this.sourceSet.size());
88+
result = CollectionUtils.newLinkedHashSet(this.sourceSet.size());
8989
}
9090
Class<?> valueType = null;
9191
if (this.targetSetClass != null) {

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.springframework.core.ResolvableType;
7676
import org.springframework.lang.Nullable;
7777
import org.springframework.util.ClassUtils;
78+
import org.springframework.util.CollectionUtils;
7879
import org.springframework.util.ObjectUtils;
7980
import org.springframework.util.ReflectionUtils;
8081
import org.springframework.util.ReflectionUtils.MethodCallback;
@@ -616,7 +617,7 @@ protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable
616617
}
617618
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
618619
String[] dependentBeans = getDependentBeans(beanName);
619-
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
620+
Set<String> actualDependentBeans = CollectionUtils.newLinkedHashSet(dependentBeans.length);
620621
for (String dependentBean : dependentBeans) {
621622
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
622623
actualDependentBeans.add(dependentBean);
@@ -765,7 +766,7 @@ protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition m
765766
paramNames = pnd.getParameterNames(candidate);
766767
}
767768
}
768-
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
769+
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = CollectionUtils.newHashSet(paramTypes.length);
769770
Object[] args = new Object[paramTypes.length];
770771
for (int i = 0; i < args.length; i++) {
771772
ConstructorArgumentValues.ValueHolder valueHolder = cav.getArgumentValue(

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.Arrays;
2222
import java.util.Collection;
2323
import java.util.HashMap;
24-
import java.util.HashSet;
2524
import java.util.LinkedHashMap;
2625
import java.util.LinkedHashSet;
2726
import java.util.List;
@@ -73,6 +72,7 @@
7372
import org.springframework.lang.Nullable;
7473
import org.springframework.util.Assert;
7574
import org.springframework.util.ClassUtils;
75+
import org.springframework.util.CollectionUtils;
7676
import org.springframework.util.ObjectUtils;
7777
import org.springframework.util.StringUtils;
7878
import org.springframework.util.StringValueResolver;
@@ -1152,7 +1152,7 @@ protected void beforePrototypeCreation(String beanName) {
11521152
this.prototypesCurrentlyInCreation.set(beanName);
11531153
}
11541154
else if (curVal instanceof String strValue) {
1155-
Set<String> beanNameSet = new HashSet<>(2);
1155+
Set<String> beanNameSet = CollectionUtils.newHashSet(2);
11561156
beanNameSet.add(strValue);
11571157
beanNameSet.add(beanName);
11581158
this.prototypesCurrentlyInCreation.set(beanNameSet);

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionValueResolver.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ private List<?> resolveManagedList(Object argName, List<?> ml) {
466466
* For each element in the managed set, resolve reference if necessary.
467467
*/
468468
private Set<?> resolveManagedSet(Object argName, Set<?> ms) {
469-
Set<Object> resolved = new LinkedHashSet<>(ms.size());
469+
Set<Object> resolved = CollectionUtils.newLinkedHashSet(ms.size());
470470
int i = 0;
471471
for (Object m : ms) {
472472
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.springframework.lang.Nullable;
7171
import org.springframework.util.Assert;
7272
import org.springframework.util.ClassUtils;
73+
import org.springframework.util.CollectionUtils;
7374
import org.springframework.util.MethodInvoker;
7475
import org.springframework.util.ObjectUtils;
7576
import org.springframework.util.ReflectionUtils;
@@ -598,7 +599,7 @@ else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
598599
}
599600
}
600601
else if (resolvedValues != null) {
601-
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
602+
Set<ValueHolder> valueHolders = CollectionUtils.newLinkedHashSet(resolvedValues.getArgumentCount());
602603
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
603604
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
604605
for (ValueHolder value : valueHolders) {

Diff for: spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/GenericBean.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Set;
2929

3030
import org.springframework.core.io.Resource;
31+
import org.springframework.util.CollectionUtils;
3132

3233
/**
3334
* @author Juergen Hoeller
@@ -266,7 +267,7 @@ public Set<CustomEnum> getCustomEnumSetMismatch() {
266267
}
267268

268269
public void setCustomEnumSetMismatch(Set<String> customEnumSet) {
269-
this.customEnumSet = new HashSet<>(customEnumSet.size());
270+
this.customEnumSet = CollectionUtils.newHashSet(customEnumSet.size());
270271
for (String customEnumName : customEnumSet) {
271272
this.customEnumSet.add(CustomEnum.valueOf(customEnumName));
272273
}

Diff for: spring-context/src/main/java/org/springframework/cache/interceptor/CacheOperation.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
package org.springframework.cache.interceptor;
1818

1919
import java.util.Collections;
20-
import java.util.LinkedHashSet;
2120
import java.util.Set;
2221

2322
import org.springframework.lang.Nullable;
2423
import org.springframework.util.Assert;
24+
import org.springframework.util.CollectionUtils;
2525

2626
/**
2727
* Base class for cache operations.
@@ -158,7 +158,7 @@ public void setCacheName(String cacheName) {
158158
}
159159

160160
public void setCacheNames(String... cacheNames) {
161-
this.cacheNames = new LinkedHashSet<>(cacheNames.length);
161+
this.cacheNames = CollectionUtils.newLinkedHashSet(cacheNames.length);
162162
for (String cacheName : cacheNames) {
163163
Assert.hasText(cacheName, "Cache name must be non-empty if specified");
164164
this.cacheNames.add(cacheName);

Diff for: spring-context/src/main/java/org/springframework/cache/support/AbstractCacheManager.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.cache.Cache;
2828
import org.springframework.cache.CacheManager;
2929
import org.springframework.lang.Nullable;
30+
import org.springframework.util.CollectionUtils;
3031

3132
/**
3233
* Abstract base class implementing the common {@link CacheManager} methods.
@@ -64,7 +65,7 @@ public void initializeCaches() {
6465
synchronized (this.cacheMap) {
6566
this.cacheNames = Collections.emptySet();
6667
this.cacheMap.clear();
67-
Set<String> cacheNames = new LinkedHashSet<>(caches.size());
68+
Set<String> cacheNames = CollectionUtils.newLinkedHashSet(caches.size());
6869
for (Cache cache : caches) {
6970
String name = cache.getName();
7071
this.cacheMap.put(name, decorateCache(cache));

Diff for: spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.springframework.context.annotation;
1818

1919
import java.lang.annotation.Annotation;
20-
import java.util.LinkedHashSet;
2120
import java.util.Set;
2221
import java.util.function.Predicate;
2322

@@ -38,6 +37,7 @@
3837
import org.springframework.core.type.AnnotationMetadata;
3938
import org.springframework.lang.Nullable;
4039
import org.springframework.util.ClassUtils;
40+
import org.springframework.util.CollectionUtils;
4141

4242
/**
4343
* Utility class that allows for convenient registration of common
@@ -154,7 +154,7 @@ public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
154154
}
155155
}
156156

157-
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
157+
Set<BeanDefinitionHolder> beanDefs = CollectionUtils.newLinkedHashSet(6);
158158

159159
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
160160
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);

Diff for: spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import org.springframework.lang.Nullable;
7272
import org.springframework.util.Assert;
7373
import org.springframework.util.ClassUtils;
74+
import org.springframework.util.CollectionUtils;
7475
import org.springframework.util.ObjectUtils;
7576
import org.springframework.util.ReflectionUtils;
7677
import org.springframework.util.StringUtils;
@@ -148,7 +149,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
148149
private static final boolean jndiPresent = ClassUtils.isPresent(
149150
"javax.naming.InitialContext", CommonAnnotationBeanPostProcessor.class.getClassLoader());
150151

151-
private static final Set<Class<? extends Annotation>> resourceAnnotationTypes = new LinkedHashSet<>(4);
152+
private static final Set<Class<? extends Annotation>> resourceAnnotationTypes = CollectionUtils.newLinkedHashSet(3);
152153

153154
@Nullable
154155
private static final Class<? extends Annotation> jakartaResourceType;

Diff for: spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass)
437437
Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
438438
if (asmMethods.size() >= beanMethods.size()) {
439439
Set<MethodMetadata> candidateMethods = new LinkedHashSet<>(beanMethods);
440-
Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
440+
Set<MethodMetadata> selectedMethods = CollectionUtils.newLinkedHashSet(asmMethods.size());
441441
for (MethodMetadata asmMethod : asmMethods) {
442442
for (Iterator<MethodMetadata> it = candidateMethods.iterator(); it.hasNext();) {
443443
MethodMetadata beanMethod = it.next();

Diff for: spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.
410410
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
411411

412412
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
413-
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
413+
Set<ConfigurationClass> alreadyParsed = CollectionUtils.newHashSet(configCandidates.size());
414414
do {
415415
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
416416
parser.parse(candidates);
@@ -433,7 +433,7 @@ else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.
433433
if (registry.getBeanDefinitionCount() > candidateNames.length) {
434434
String[] newCandidateNames = registry.getBeanDefinitionNames();
435435
Set<String> oldCandidateNames = Set.of(candidateNames);
436-
Set<String> alreadyParsedClasses = new HashSet<>();
436+
Set<String> alreadyParsedClasses = CollectionUtils.newHashSet(alreadyParsed.size());
437437
for (ConfigurationClass configurationClass : alreadyParsed) {
438438
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
439439
}

Diff for: spring-context/src/main/java/org/springframework/jmx/export/MBeanExporter.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.HashMap;
2222
import java.util.HashSet;
2323
import java.util.LinkedHashMap;
24-
import java.util.LinkedHashSet;
2524
import java.util.List;
2625
import java.util.Map;
2726
import java.util.Set;
@@ -883,7 +882,7 @@ private ModelMBeanInfo getMBeanInfo(Object managedBean, String beanKey) throws J
883882
*/
884883
private void autodetect(Map<String, Object> beans, AutodetectCallback callback) {
885884
Assert.state(this.beanFactory != null, "No BeanFactory set");
886-
Set<String> beanNames = new LinkedHashSet<>(this.beanFactory.getBeanDefinitionCount());
885+
Set<String> beanNames = CollectionUtils.newLinkedHashSet(this.beanFactory.getBeanDefinitionCount());
887886
Collections.addAll(beanNames, this.beanFactory.getBeanDefinitionNames());
888887
if (this.beanFactory instanceof ConfigurableBeanFactory cbf) {
889888
Collections.addAll(beanNames, cbf.getSingletonNames());

0 commit comments

Comments
 (0)