Skip to content

Commit d5e637a

Browse files
committed
Restore independent LinkedMultiValueMap implementation (without base class)
Closes gh-25960 (cherry picked from commit 82835b9)
1 parent e913167 commit d5e637a

File tree

2 files changed

+148
-4
lines changed

2 files changed

+148
-4
lines changed

spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java

Lines changed: 143 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
package org.springframework.util;
1818

1919
import java.io.Serializable;
20+
import java.util.Collection;
2021
import java.util.LinkedHashMap;
2122
import java.util.LinkedList;
2223
import java.util.List;
2324
import java.util.Map;
25+
import java.util.Set;
26+
27+
import org.springframework.lang.Nullable;
2428

2529
/**
2630
* Simple implementation of {@link MultiValueMap} that wraps a {@link LinkedHashMap},
@@ -35,16 +39,18 @@
3539
* @param <K> the key type
3640
* @param <V> the value element type
3741
*/
38-
public class LinkedMultiValueMap<K, V> extends MultiValueMapAdapter<K, V> implements Serializable, Cloneable {
42+
public class LinkedMultiValueMap<K, V> implements MultiValueMap<K, V>, Serializable, Cloneable {
3943

4044
private static final long serialVersionUID = 3801124242820219131L;
4145

46+
private final Map<K, List<V>> targetMap;
47+
4248

4349
/**
4450
* Create a new LinkedMultiValueMap that wraps a {@link LinkedHashMap}.
4551
*/
4652
public LinkedMultiValueMap() {
47-
super(new LinkedHashMap<>());
53+
this.targetMap = new LinkedHashMap<>();
4854
}
4955

5056
/**
@@ -53,7 +59,7 @@ public LinkedMultiValueMap() {
5359
* @param initialCapacity the initial capacity
5460
*/
5561
public LinkedMultiValueMap(int initialCapacity) {
56-
super(new LinkedHashMap<>(initialCapacity));
62+
this.targetMap = new LinkedHashMap<>(initialCapacity);
5763
}
5864

5965
/**
@@ -65,7 +71,140 @@ public LinkedMultiValueMap(int initialCapacity) {
6571
* @see #deepCopy()
6672
*/
6773
public LinkedMultiValueMap(Map<K, List<V>> otherMap) {
68-
super(new LinkedHashMap<>(otherMap));
74+
this.targetMap = new LinkedHashMap<>(otherMap);
75+
}
76+
77+
78+
// MultiValueMap implementation
79+
80+
@Override
81+
@Nullable
82+
public V getFirst(K key) {
83+
List<V> values = this.targetMap.get(key);
84+
return (values != null && !values.isEmpty() ? values.get(0) : null);
85+
}
86+
87+
@Override
88+
public void add(K key, @Nullable V value) {
89+
List<V> values = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
90+
values.add(value);
91+
}
92+
93+
@Override
94+
public void addAll(K key, List<? extends V> values) {
95+
List<V> currentValues = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
96+
currentValues.addAll(values);
97+
}
98+
99+
@Override
100+
public void addAll(MultiValueMap<K, V> values) {
101+
for (Entry<K, List<V>> entry : values.entrySet()) {
102+
addAll(entry.getKey(), entry.getValue());
103+
}
104+
}
105+
106+
@Override
107+
public void set(K key, @Nullable V value) {
108+
List<V> values = new LinkedList<>();
109+
values.add(value);
110+
this.targetMap.put(key, values);
111+
}
112+
113+
@Override
114+
public void setAll(Map<K, V> values) {
115+
values.forEach(this::set);
116+
}
117+
118+
@Override
119+
public Map<K, V> toSingleValueMap() {
120+
Map<K, V> singleValueMap = new LinkedHashMap<>(this.targetMap.size());
121+
this.targetMap.forEach((key, values) -> {
122+
if (values != null && !values.isEmpty()) {
123+
singleValueMap.put(key, values.get(0));
124+
}
125+
});
126+
return singleValueMap;
127+
}
128+
129+
130+
// Map implementation
131+
132+
@Override
133+
public int size() {
134+
return this.targetMap.size();
135+
}
136+
137+
@Override
138+
public boolean isEmpty() {
139+
return this.targetMap.isEmpty();
140+
}
141+
142+
@Override
143+
public boolean containsKey(Object key) {
144+
return this.targetMap.containsKey(key);
145+
}
146+
147+
@Override
148+
public boolean containsValue(Object value) {
149+
return this.targetMap.containsValue(value);
150+
}
151+
152+
@Override
153+
@Nullable
154+
public List<V> get(Object key) {
155+
return this.targetMap.get(key);
156+
}
157+
158+
@Override
159+
@Nullable
160+
public List<V> put(K key, List<V> value) {
161+
return this.targetMap.put(key, value);
162+
}
163+
164+
@Override
165+
@Nullable
166+
public List<V> remove(Object key) {
167+
return this.targetMap.remove(key);
168+
}
169+
170+
@Override
171+
public void putAll(Map<? extends K, ? extends List<V>> map) {
172+
this.targetMap.putAll(map);
173+
}
174+
175+
@Override
176+
public void clear() {
177+
this.targetMap.clear();
178+
}
179+
180+
@Override
181+
public Set<K> keySet() {
182+
return this.targetMap.keySet();
183+
}
184+
185+
@Override
186+
public Collection<List<V>> values() {
187+
return this.targetMap.values();
188+
}
189+
190+
@Override
191+
public Set<Entry<K, List<V>>> entrySet() {
192+
return this.targetMap.entrySet();
193+
}
194+
195+
@Override
196+
public boolean equals(@Nullable Object other) {
197+
return (this == other || this.targetMap.equals(other));
198+
}
199+
200+
@Override
201+
public int hashCode() {
202+
return this.targetMap.hashCode();
203+
}
204+
205+
@Override
206+
public String toString() {
207+
return this.targetMap.toString();
69208
}
70209

71210

spring-core/src/main/java/org/springframework/util/MultiValueMapAdapter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class MultiValueMapAdapter<K, V> implements MultiValueMap<K, V>, Serializable {
4848
}
4949

5050

51+
// MultiValueMap implementation
52+
5153
@Override
5254
@Nullable
5355
public V getFirst(K key) {
@@ -97,6 +99,9 @@ public Map<K, V> toSingleValueMap() {
9799
return singleValueMap;
98100
}
99101

102+
103+
// Map implementation
104+
100105
@Override
101106
public int size() {
102107
return this.targetMap.size();

0 commit comments

Comments
 (0)