Skip to content

Commit 0211016

Browse files
committed
Consistent support for MultiValueMap and common Map implementations
Closes gh-30440
1 parent 08fe123 commit 0211016

File tree

2 files changed

+53
-49
lines changed

2 files changed

+53
-49
lines changed

Diff for: spring-core/src/main/java/org/springframework/core/CollectionFactory.java

+24-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -68,6 +68,7 @@ public final class CollectionFactory {
6868
approximableCollectionTypes.add(SortedSet.class);
6969
approximableCollectionTypes.add(NavigableSet.class);
7070
approximableMapTypes.add(Map.class);
71+
approximableMapTypes.add(MultiValueMap.class);
7172
approximableMapTypes.add(SortedMap.class);
7273
approximableMapTypes.add(NavigableMap.class);
7374

@@ -80,6 +81,7 @@ public final class CollectionFactory {
8081
approximableCollectionTypes.add(EnumSet.class);
8182
approximableMapTypes.add(HashMap.class);
8283
approximableMapTypes.add(LinkedHashMap.class);
84+
approximableMapTypes.add(LinkedMultiValueMap.class);
8385
approximableMapTypes.add(TreeMap.class);
8486
approximableMapTypes.add(EnumMap.class);
8587
}
@@ -121,13 +123,7 @@ public static boolean isApproximableCollectionType(@Nullable Class<?> collection
121123
*/
122124
@SuppressWarnings({"rawtypes", "unchecked", "cast"})
123125
public static <E> Collection<E> createApproximateCollection(@Nullable Object collection, int capacity) {
124-
if (collection instanceof LinkedList) {
125-
return new LinkedList<>();
126-
}
127-
else if (collection instanceof List) {
128-
return new ArrayList<>(capacity);
129-
}
130-
else if (collection instanceof EnumSet) {
126+
if (collection instanceof EnumSet) {
131127
// Cast is necessary for compilation in Eclipse 4.4.1.
132128
Collection<E> enumSet = (Collection<E>) EnumSet.copyOf((EnumSet) collection);
133129
enumSet.clear();
@@ -136,6 +132,12 @@ else if (collection instanceof EnumSet) {
136132
else if (collection instanceof SortedSet) {
137133
return new TreeSet<>(((SortedSet<E>) collection).comparator());
138134
}
135+
if (collection instanceof LinkedList) {
136+
return new LinkedList<>();
137+
}
138+
else if (collection instanceof List) {
139+
return new ArrayList<>(capacity);
140+
}
139141
else {
140142
return new LinkedHashSet<>(capacity);
141143
}
@@ -191,8 +193,8 @@ else if (ArrayList.class == collectionType || List.class == collectionType) {
191193
else if (LinkedList.class == collectionType) {
192194
return new LinkedList<>();
193195
}
194-
else if (TreeSet.class == collectionType || NavigableSet.class == collectionType
195-
|| SortedSet.class == collectionType) {
196+
else if (TreeSet.class == collectionType || NavigableSet.class == collectionType ||
197+
SortedSet.class == collectionType) {
196198
return new TreeSet<>();
197199
}
198200
else if (EnumSet.class.isAssignableFrom(collectionType)) {
@@ -251,6 +253,9 @@ public static <K, V> Map<K, V> createApproximateMap(@Nullable Object map, int ca
251253
else if (map instanceof SortedMap) {
252254
return new TreeMap<>(((SortedMap<K, V>) map).comparator());
253255
}
256+
else if (map instanceof MultiValueMap) {
257+
return new LinkedMultiValueMap(capacity);
258+
}
254259
else {
255260
return new LinkedHashMap<>(capacity);
256261
}
@@ -297,26 +302,21 @@ public static <K, V> Map<K, V> createMap(Class<?> mapType, int capacity) {
297302
@SuppressWarnings({"rawtypes", "unchecked"})
298303
public static <K, V> Map<K, V> createMap(Class<?> mapType, @Nullable Class<?> keyType, int capacity) {
299304
Assert.notNull(mapType, "Map type must not be null");
300-
if (mapType.isInterface()) {
301-
if (Map.class == mapType) {
302-
return new LinkedHashMap<>(capacity);
303-
}
304-
else if (SortedMap.class == mapType || NavigableMap.class == mapType) {
305-
return new TreeMap<>();
306-
}
307-
else if (MultiValueMap.class == mapType) {
308-
return new LinkedMultiValueMap();
309-
}
310-
else {
311-
throw new IllegalArgumentException("Unsupported Map interface: " + mapType.getName());
312-
}
305+
if (LinkedHashMap.class == mapType || HashMap.class == mapType || Map.class == mapType) {
306+
return new LinkedHashMap<>(capacity);
307+
}
308+
else if (LinkedMultiValueMap.class == mapType || MultiValueMap.class == mapType) {
309+
return new LinkedMultiValueMap();
310+
}
311+
else if (TreeMap.class == mapType || SortedMap.class == mapType || NavigableMap.class == mapType) {
312+
return new TreeMap<>();
313313
}
314314
else if (EnumMap.class == mapType) {
315315
Assert.notNull(keyType, "Cannot create EnumMap for unknown key type");
316316
return new EnumMap(asEnumType(keyType));
317317
}
318318
else {
319-
if (!Map.class.isAssignableFrom(mapType)) {
319+
if (mapType.isInterface() || !Map.class.isAssignableFrom(mapType)) {
320320
throw new IllegalArgumentException("Unsupported Map type: " + mapType.getName());
321321
}
322322
try {

Diff for: spring-core/src/test/java/org/springframework/core/CollectionFactoryTests.java

+29-25
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -209,21 +209,23 @@ void createApproximateMapFromNonEmptyEnumMap() {
209209
@Test
210210
void createsCollectionsCorrectly() {
211211
// interfaces
212-
assertThat(createCollection(List.class, 0)).isInstanceOf(ArrayList.class);
213-
assertThat(createCollection(Set.class, 0)).isInstanceOf(LinkedHashSet.class);
214-
assertThat(createCollection(Collection.class, 0)).isInstanceOf(LinkedHashSet.class);
215-
assertThat(createCollection(SortedSet.class, 0)).isInstanceOf(TreeSet.class);
216-
assertThat(createCollection(NavigableSet.class, 0)).isInstanceOf(TreeSet.class);
217-
218-
assertThat(createCollection(List.class, String.class, 0)).isInstanceOf(ArrayList.class);
219-
assertThat(createCollection(Set.class, String.class, 0)).isInstanceOf(LinkedHashSet.class);
220-
assertThat(createCollection(Collection.class, String.class, 0)).isInstanceOf(LinkedHashSet.class);
221-
assertThat(createCollection(SortedSet.class, String.class, 0)).isInstanceOf(TreeSet.class);
222-
assertThat(createCollection(NavigableSet.class, String.class, 0)).isInstanceOf(TreeSet.class);
212+
testCollection(List.class, ArrayList.class);
213+
testCollection(Set.class, LinkedHashSet.class);
214+
testCollection(Collection.class, LinkedHashSet.class);
215+
testCollection(SortedSet.class, TreeSet.class);
216+
testCollection(NavigableSet.class, TreeSet.class);
223217

224218
// concrete types
225-
assertThat(createCollection(HashSet.class, 0)).isInstanceOf(HashSet.class);
226-
assertThat(createCollection(HashSet.class, String.class, 0)).isInstanceOf(HashSet.class);
219+
testCollection(ArrayList.class, ArrayList.class);
220+
testCollection(HashSet.class, LinkedHashSet.class);
221+
testCollection(LinkedHashSet.class, LinkedHashSet.class);
222+
testCollection(TreeSet.class, TreeSet.class);
223+
}
224+
225+
private void testCollection(Class<?> collectionType, Class<?> resultType) {
226+
assertThat(CollectionFactory.isApproximableCollectionType(collectionType)).isTrue();
227+
assertThat(createCollection(collectionType, 0)).isInstanceOf(resultType);
228+
assertThat(createCollection(collectionType, String.class, 0)).isInstanceOf(resultType);
227229
}
228230

229231
@Test
@@ -258,20 +260,22 @@ void rejectsNullCollectionType() {
258260
@Test
259261
void createsMapsCorrectly() {
260262
// interfaces
261-
assertThat(createMap(Map.class, 0)).isInstanceOf(LinkedHashMap.class);
262-
assertThat(createMap(SortedMap.class, 0)).isInstanceOf(TreeMap.class);
263-
assertThat(createMap(NavigableMap.class, 0)).isInstanceOf(TreeMap.class);
264-
assertThat(createMap(MultiValueMap.class, 0)).isInstanceOf(LinkedMultiValueMap.class);
265-
266-
assertThat(createMap(Map.class, String.class, 0)).isInstanceOf(LinkedHashMap.class);
267-
assertThat(createMap(SortedMap.class, String.class, 0)).isInstanceOf(TreeMap.class);
268-
assertThat(createMap(NavigableMap.class, String.class, 0)).isInstanceOf(TreeMap.class);
269-
assertThat(createMap(MultiValueMap.class, String.class, 0)).isInstanceOf(LinkedMultiValueMap.class);
263+
testMap(Map.class, LinkedHashMap.class);
264+
testMap(SortedMap.class, TreeMap.class);
265+
testMap(NavigableMap.class, TreeMap.class);
266+
testMap(MultiValueMap.class, LinkedMultiValueMap.class);
270267

271268
// concrete types
272-
assertThat(createMap(HashMap.class, 0)).isInstanceOf(HashMap.class);
269+
testMap(HashMap.class, LinkedHashMap.class);
270+
testMap(LinkedHashMap.class, LinkedHashMap.class);
271+
testMap(TreeMap.class, TreeMap.class);
272+
testMap(LinkedMultiValueMap.class, LinkedMultiValueMap.class);
273+
}
273274

274-
assertThat(createMap(HashMap.class, String.class, 0)).isInstanceOf(HashMap.class);
275+
private void testMap(Class<?> mapType, Class<?> resultType) {
276+
assertThat(CollectionFactory.isApproximableMapType(mapType)).isTrue();
277+
assertThat(createMap(mapType, 0)).isInstanceOf(resultType);
278+
assertThat(createMap(mapType, String.class, 0)).isInstanceOf(resultType);
275279
}
276280

277281
@Test

0 commit comments

Comments
 (0)