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

@@ -34,7 +34,6 @@ import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -752,7 +751,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
String value = getFirst(ALLOW);
if (StringUtils.hasLength(value)) {
String[] tokens = StringUtils.tokenizeToStringArray(value, ",");
Set<HttpMethod> result = new LinkedHashSet<>(tokens.length);
Set<HttpMethod> result = CollectionUtils.newLinkedHashSet(tokens.length);
for (String token : tokens) {
HttpMethod method = HttpMethod.valueOf(token);
result.add(method);

View File

@@ -22,7 +22,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -163,7 +162,7 @@ public final class HttpComponentsHeadersAdapter implements MultiValueMap<String,
@Override
public Set<String> keySet() {
Set<String> keys = new LinkedHashSet<>(size());
Set<String> keys = CollectionUtils.newLinkedHashSet(size());
for (Header header : this.message.getHeaders()) {
keys.add(header.getName());
}

View File

@@ -17,7 +17,6 @@
package org.springframework.web;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import jakarta.servlet.ServletException;
@@ -28,6 +27,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ProblemDetail;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -107,7 +107,7 @@ public class HttpRequestMethodNotSupportedException extends ServletException imp
if (this.supportedMethods == null) {
return null;
}
Set<HttpMethod> supportedMethods = new LinkedHashSet<>(this.supportedMethods.length);
Set<HttpMethod> supportedMethods = CollectionUtils.newLinkedHashSet(this.supportedMethods.length);
for (String value : this.supportedMethods) {
HttpMethod method = HttpMethod.valueOf(value);
supportedMethods.add(method);

View File

@@ -18,7 +18,6 @@ package org.springframework.web.accept;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -29,6 +28,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
/**
* An implementation of {@code MediaTypeFileExtensionResolver} that maintains
@@ -55,7 +55,7 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
*/
public MappingMediaTypeFileExtensionResolver(@Nullable Map<String, MediaType> mediaTypes) {
if (mediaTypes != null) {
Set<String> allFileExtensions = new HashSet<>(mediaTypes.size());
Set<String> allFileExtensions = CollectionUtils.newHashSet(mediaTypes.size());
mediaTypes.forEach((extension, mediaType) -> {
String lowerCaseExtension = extension.toLowerCase(Locale.ENGLISH);
this.mediaTypes.put(lowerCaseExtension, mediaType);

View File

@@ -19,7 +19,6 @@ package org.springframework.web.cors;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
@@ -657,7 +656,7 @@ public class CorsConfiguration {
if (source.contains(ALL) || other.contains(ALL)) {
return ALL_LIST;
}
Set<String> combined = new LinkedHashSet<>(source.size() + other.size());
Set<String> combined = CollectionUtils.newLinkedHashSet(source.size() + other.size());
combined.addAll(source);
combined.addAll(other);
return new ArrayList<>(combined);
@@ -675,7 +674,7 @@ public class CorsConfiguration {
if (source.contains(ALL_PATTERN) || other.contains(ALL_PATTERN)) {
return ALL_PATTERN_LIST;
}
Set<OriginPattern> combined = new LinkedHashSet<>(source.size() + other.size());
Set<OriginPattern> combined = CollectionUtils.newLinkedHashSet(source.size() + other.size());
combined.addAll(source);
combined.addAll(other);
return new ArrayList<>(combined);

View File

@@ -37,6 +37,7 @@ import jakarta.servlet.http.Part;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -91,7 +92,7 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
private void parseRequest(HttpServletRequest request) {
try {
Collection<Part> parts = request.getParts();
this.multipartParameterNames = new LinkedHashSet<>(parts.size());
this.multipartParameterNames = CollectionUtils.newLinkedHashSet(parts.size());
MultiValueMap<String, MultipartFile> files = new LinkedMultiValueMap<>(parts.size());
for (Part part : parts) {
String headerValue = part.getHeader(HttpHeaders.CONTENT_DISPOSITION);