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:
Patrick Strawderman
2024-02-18 14:05:31 -08:00
committed by Sam Brannen
parent 6383a0d7ca
commit e1a32d4ba9
47 changed files with 114 additions and 75 deletions

View File

@@ -88,6 +88,7 @@ import org.springframework.javapoet.CodeBlock;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
@@ -163,7 +164,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
protected final Log logger = LogFactory.getLog(getClass());
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = CollectionUtils.newLinkedHashSet(4);
private String requiredParameterName = "required";

View File

@@ -363,7 +363,7 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
}
public void checkInitDestroyMethods(RootBeanDefinition beanDefinition) {
Set<LifecycleMethod> checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
Set<LifecycleMethod> checkedInitMethods = CollectionUtils.newLinkedHashSet(this.initMethods.size());
for (LifecycleMethod lifecycleMethod : this.initMethods) {
String methodIdentifier = lifecycleMethod.getIdentifier();
if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
@@ -374,7 +374,7 @@ public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareB
}
}
}
Set<LifecycleMethod> checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
Set<LifecycleMethod> checkedDestroyMethods = CollectionUtils.newLinkedHashSet(this.destroyMethods.size());
for (LifecycleMethod lifecycleMethod : this.destroyMethods) {
String methodIdentifier = lifecycleMethod.getIdentifier();
if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {

View File

@@ -23,13 +23,13 @@ import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
/**
@@ -124,7 +124,7 @@ public class InjectionMetadata {
this.checkedElements = Collections.emptySet();
}
else {
Set<InjectedElement> checkedElements = new LinkedHashSet<>((this.injectedElements.size() * 4 / 3) + 1);
Set<InjectedElement> checkedElements = CollectionUtils.newLinkedHashSet(this.injectedElements.size());
for (InjectedElement element : this.injectedElements) {
Member member = element.getMember();
if (!beanDefinition.isExternallyManagedConfigMember(member)) {

View File

@@ -19,7 +19,6 @@ package org.springframework.beans.factory.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
@@ -40,6 +39,7 @@ import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
/**
@@ -59,7 +59,7 @@ import org.springframework.util.ObjectUtils;
*/
public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver {
private final Set<Class<? extends Annotation>> qualifierTypes = new LinkedHashSet<>(2);
private final Set<Class<? extends Annotation>> qualifierTypes = CollectionUtils.newLinkedHashSet(2);
private Class<? extends Annotation> valueAnnotationType = Value.class;

View File

@@ -18,7 +18,6 @@ package org.springframework.beans.factory.aot;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
@@ -34,6 +33,7 @@ import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.function.ThrowingConsumer;
@@ -165,7 +165,7 @@ public final class AutowiredMethodArgumentsResolver extends AutowiredElementReso
AutowireCapableBeanFactory autowireCapableBeanFactory = (AutowireCapableBeanFactory) beanFactory;
int argumentCount = method.getParameterCount();
Object[] arguments = new Object[argumentCount];
Set<String> autowiredBeanNames = new LinkedHashSet<>(argumentCount);
Set<String> autowiredBeanNames = CollectionUtils.newLinkedHashSet(argumentCount);
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < argumentCount; i++) {
MethodParameter parameter = new MethodParameter(method, i);

View File

@@ -22,7 +22,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
@@ -49,6 +48,7 @@ import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.function.ThrowingBiFunction;
@@ -289,7 +289,7 @@ public final class BeanInstanceSupplier<T> extends AutowiredElementResolver impl
beanFactory, registeredBean.getBeanName(), beanDefinition, beanFactory.getTypeConverter());
ConstructorArgumentValues values = resolveConstructorArguments(
valueResolver, beanDefinition.getConstructorArgumentValues());
Set<ValueHolder> usedValueHolders = new HashSet<>(parameters.length);
Set<ValueHolder> usedValueHolders = CollectionUtils.newHashSet(parameters.length);
for (int i = 0; i < parameters.length; i++) {
Class<?> parameterType = parameters[i].getType();
String parameterName = (parameters[i].isNamePresent() ? parameters[i].getName() : null);

View File

@@ -16,13 +16,13 @@
package org.springframework.beans.factory.config;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.TypeConverter;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
/**
* Simple factory for shared Set instances. Allows for central setup
@@ -85,7 +85,7 @@ public class SetFactoryBean extends AbstractFactoryBean<Set<Object>> {
result = BeanUtils.instantiateClass(this.targetSetClass);
}
else {
result = new LinkedHashSet<>(this.sourceSet.size());
result = CollectionUtils.newLinkedHashSet(this.sourceSet.size());
}
Class<?> valueType = null;
if (this.targetSetClass != null) {

View File

@@ -75,6 +75,7 @@ import org.springframework.core.PriorityOrdered;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodCallback;
@@ -616,7 +617,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
Set<String> actualDependentBeans = CollectionUtils.newLinkedHashSet(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
@@ -765,7 +766,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
paramNames = pnd.getParameterNames(candidate);
}
}
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = CollectionUtils.newHashSet(paramTypes.length);
Object[] args = new Object[paramTypes.length];
for (int i = 0; i < args.length; i++) {
ConstructorArgumentValues.ValueHolder valueHolder = cav.getArgumentValue(

View File

@@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -73,6 +72,7 @@ import org.springframework.core.metrics.StartupStep;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;
@@ -1152,7 +1152,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
this.prototypesCurrentlyInCreation.set(beanName);
}
else if (curVal instanceof String strValue) {
Set<String> beanNameSet = new HashSet<>(2);
Set<String> beanNameSet = CollectionUtils.newHashSet(2);
beanNameSet.add(strValue);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);

View File

@@ -466,7 +466,7 @@ public class BeanDefinitionValueResolver {
* For each element in the managed set, resolve reference if necessary.
*/
private Set<?> resolveManagedSet(Object argName, Set<?> ms) {
Set<Object> resolved = new LinkedHashSet<>(ms.size());
Set<Object> resolved = CollectionUtils.newLinkedHashSet(ms.size());
int i = 0;
for (Object m : ms) {
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));

View File

@@ -70,6 +70,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MethodInvoker;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -598,7 +599,7 @@ class ConstructorResolver {
}
}
else if (resolvedValues != null) {
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
Set<ValueHolder> valueHolders = CollectionUtils.newLinkedHashSet(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ValueHolder value : valueHolders) {

View File

@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
import org.springframework.core.io.Resource;
import org.springframework.util.CollectionUtils;
/**
* @author Juergen Hoeller
@@ -266,7 +267,7 @@ public class GenericBean<T> {
}
public void setCustomEnumSetMismatch(Set<String> customEnumSet) {
this.customEnumSet = new HashSet<>(customEnumSet.size());
this.customEnumSet = CollectionUtils.newHashSet(customEnumSet.size());
for (String customEnumName : customEnumSet) {
this.customEnumSet.add(CustomEnum.valueOf(customEnumName));
}