Skip to content

Commit f927ff6

Browse files
committed
Revise @⁠Nullable declarations for contains*() in CollectionUtils
Closes gh-35023
1 parent 2c0f01e commit f927ff6

File tree

2 files changed

+75
-35
lines changed

2 files changed

+75
-35
lines changed

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

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
* @author Juergen Hoeller
4646
* @author Rob Harrop
4747
* @author Arjen Poutsma
48+
* @author Sam Brannen
4849
* @since 1.1.3
4950
*/
5051
public abstract class CollectionUtils {
@@ -195,13 +196,15 @@ public static <K, V> void mergePropertiesIntoMap(@Nullable Properties props, Map
195196

196197

197198
/**
198-
* Check whether the given Iterator contains the given element.
199-
* @param iterator the Iterator to check
199+
* Check whether the given {@link Iterator} contains the given element.
200+
* @param iterator the {@code Iterator} to check
200201
* @param element the element to look for
201202
* @return {@code true} if found, {@code false} otherwise
202203
*/
203204
@Contract("null, _ -> false")
204-
public static boolean contains(@Nullable Iterator<?> iterator, Object element) {
205+
public static boolean contains(@Nullable Iterator<? extends @Nullable Object> iterator,
206+
@Nullable Object element) {
207+
205208
if (iterator != null) {
206209
while (iterator.hasNext()) {
207210
Object candidate = iterator.next();
@@ -214,13 +217,15 @@ public static boolean contains(@Nullable Iterator<?> iterator, Object element) {
214217
}
215218

216219
/**
217-
* Check whether the given Enumeration contains the given element.
218-
* @param enumeration the Enumeration to check
220+
* Check whether the given {@link Enumeration} contains the given element.
221+
* @param enumeration the {@code Enumeration} to check
219222
* @param element the element to look for
220223
* @return {@code true} if found, {@code false} otherwise
221224
*/
222225
@Contract("null, _ -> false")
223-
public static boolean contains(@Nullable Enumeration<?> enumeration, Object element) {
226+
public static boolean contains(@Nullable Enumeration<? extends @Nullable Object> enumeration,
227+
@Nullable Object element) {
228+
224229
if (enumeration != null) {
225230
while (enumeration.hasMoreElements()) {
226231
Object candidate = enumeration.nextElement();
@@ -233,15 +238,17 @@ public static boolean contains(@Nullable Enumeration<?> enumeration, Object elem
233238
}
234239

235240
/**
236-
* Check whether the given Collection contains the given element instance.
241+
* Check whether the given {@link Collection} contains the given element instance.
237242
* <p>Enforces the given instance to be present, rather than returning
238243
* {@code true} for an equal element as well.
239-
* @param collection the Collection to check
244+
* @param collection the {@code Collection} to check
240245
* @param element the element to look for
241246
* @return {@code true} if found, {@code false} otherwise
242247
*/
243248
@Contract("null, _ -> false")
244-
public static boolean containsInstance(@Nullable Collection<?> collection, Object element) {
249+
public static boolean containsInstance(@Nullable Collection<? extends @Nullable Object> collection,
250+
@Nullable Object element) {
251+
245252
if (collection != null) {
246253
for (Object candidate : collection) {
247254
if (candidate == element) {
@@ -255,12 +262,22 @@ public static boolean containsInstance(@Nullable Collection<?> collection, Objec
255262
/**
256263
* Return {@code true} if any element in '{@code candidates}' is
257264
* contained in '{@code source}'; otherwise returns {@code false}.
258-
* @param source the source Collection
265+
* @param source the source {@link Collection}
259266
* @param candidates the candidates to search for
260267
* @return whether any of the candidates has been found
261268
*/
262-
public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
263-
return findFirstMatch(source, candidates) != null;
269+
public static boolean containsAny(Collection<? extends @Nullable Object> source,
270+
Collection<? extends @Nullable Object> candidates) {
271+
272+
if (isEmpty(source) || isEmpty(candidates)) {
273+
return false;
274+
}
275+
for (Object candidate : candidates) {
276+
if (source.contains(candidate)) {
277+
return true;
278+
}
279+
}
280+
return false;
264281
}
265282

266283
/**

spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.Arrays;
21+
import java.util.Collections;
2122
import java.util.Enumeration;
2223
import java.util.HashMap;
2324
import java.util.HashSet;
24-
import java.util.Hashtable;
2525
import java.util.Iterator;
2626
import java.util.List;
2727
import java.util.Map;
@@ -42,6 +42,7 @@
4242
* @author Rob Harrop
4343
* @author Juergen Hoeller
4444
* @author Rick Evans
45+
* @author Sam Brannen
4546
*/
4647
class CollectionUtilsTests {
4748

@@ -100,19 +101,24 @@ void mergePropertiesIntoMap() {
100101
}
101102

102103
@Test
103-
void contains() {
104+
void containsWithIterator() {
104105
assertThat(CollectionUtils.contains((Iterator<String>) null, "myElement")).isFalse();
105-
assertThat(CollectionUtils.contains((Enumeration<String>) null, "myElement")).isFalse();
106-
assertThat(CollectionUtils.contains(new ArrayList<String>().iterator(), "myElement")).isFalse();
107-
assertThat(CollectionUtils.contains(new Hashtable<String, Object>().keys(), "myElement")).isFalse();
106+
assertThat(CollectionUtils.contains(List.of().iterator(), "myElement")).isFalse();
108107

109-
List<String> list = new ArrayList<>();
110-
list.add("myElement");
108+
List<String> list = Arrays.asList("myElement", null);
111109
assertThat(CollectionUtils.contains(list.iterator(), "myElement")).isTrue();
110+
assertThat(CollectionUtils.contains(list.iterator(), null)).isTrue();
111+
}
112112

113-
Hashtable<String, String> ht = new Hashtable<>();
114-
ht.put("myElement", "myValue");
115-
assertThat(CollectionUtils.contains(ht.keys(), "myElement")).isTrue();
113+
@Test
114+
void containsWithEnumeration() {
115+
assertThat(CollectionUtils.contains((Enumeration<String>) null, "myElement")).isFalse();
116+
assertThat(CollectionUtils.contains(Collections.enumeration(List.of()), "myElement")).isFalse();
117+
118+
List<String> list = Arrays.asList("myElement", null);
119+
Enumeration<String> enumeration = Collections.enumeration(list);
120+
assertThat(CollectionUtils.contains(enumeration, "myElement")).isTrue();
121+
assertThat(CollectionUtils.contains(enumeration, null)).isTrue();
116122
}
117123

118124
@Test
@@ -128,39 +134,49 @@ void containsAny() {
128134
candidates.add("abc");
129135

130136
assertThat(CollectionUtils.containsAny(source, candidates)).isTrue();
137+
131138
candidates.remove("def");
132139
assertThat(CollectionUtils.containsAny(source, candidates)).isTrue();
140+
133141
candidates.remove("abc");
134142
assertThat(CollectionUtils.containsAny(source, candidates)).isFalse();
143+
144+
source.add(null);
145+
assertThat(CollectionUtils.containsAny(source, candidates)).isFalse();
146+
147+
candidates.add(null);
148+
assertThat(CollectionUtils.containsAny(source, candidates)).isTrue();
135149
}
136150

137151
@Test
138152
void containsInstanceWithNullCollection() {
139-
assertThat(CollectionUtils.containsInstance(null, this)).as("Must return false if supplied Collection argument is null").isFalse();
153+
assertThat(CollectionUtils.containsInstance(null, this)).isFalse();
140154
}
141155

142156
@Test
143157
void containsInstanceWithInstancesThatAreEqualButDistinct() {
144-
List<Instance> list = new ArrayList<>();
145-
list.add(new Instance("fiona"));
146-
assertThat(CollectionUtils.containsInstance(list, new Instance("fiona"))).as("Must return false if instance is not in the supplied Collection argument").isFalse();
158+
List<Instance> list = List.of(new Instance("fiona"));
159+
assertThat(CollectionUtils.containsInstance(list, new Instance("fiona"))).isFalse();
147160
}
148161

149162
@Test
150163
void containsInstanceWithSameInstance() {
151-
List<Instance> list = new ArrayList<>();
152-
list.add(new Instance("apple"));
153-
Instance instance = new Instance("fiona");
154-
list.add(instance);
155-
assertThat(CollectionUtils.containsInstance(list, instance)).as("Must return true if instance is in the supplied Collection argument").isTrue();
164+
Instance fiona = new Instance("fiona");
165+
Instance apple = new Instance("apple");
166+
167+
List<Instance> list = List.of(fiona, apple);
168+
assertThat(CollectionUtils.containsInstance(list, fiona)).isTrue();
156169
}
157170

158171
@Test
159172
void containsInstanceWithNullInstance() {
160-
List<Instance> list = new ArrayList<>();
161-
list.add(new Instance("apple"));
162-
list.add(new Instance("fiona"));
163-
assertThat(CollectionUtils.containsInstance(list, null)).as("Must return false if null instance is supplied").isFalse();
173+
Instance fiona = new Instance("fiona");
174+
175+
List<Instance> list = List.of(fiona);
176+
assertThat(CollectionUtils.containsInstance(list, null)).isFalse();
177+
178+
list = Arrays.asList(fiona, null);
179+
assertThat(CollectionUtils.containsInstance(list, null)).isTrue();
164180
}
165181

166182
@Test
@@ -176,6 +192,13 @@ void findFirstMatch() {
176192
candidates.add("abc");
177193

178194
assertThat(CollectionUtils.findFirstMatch(source, candidates)).isEqualTo("def");
195+
196+
source.clear();
197+
source.add(null);
198+
assertThat(CollectionUtils.findFirstMatch(source, candidates)).isNull();
199+
200+
candidates.add(null);
201+
assertThat(CollectionUtils.findFirstMatch(source, candidates)).isNull();
179202
}
180203

181204
@Test

0 commit comments

Comments
 (0)