Revise @⁠Nullable declarations for contains*() in CollectionUtils

Closes gh-35023
This commit is contained in:
Sam Brannen
2025-06-10 17:50:37 +02:00
parent 2c0f01e8ed
commit f927ff635a
2 changed files with 75 additions and 35 deletions

View File

@@ -45,6 +45,7 @@ import org.springframework.lang.Contract;
* @author Juergen Hoeller
* @author Rob Harrop
* @author Arjen Poutsma
* @author Sam Brannen
* @since 1.1.3
*/
public abstract class CollectionUtils {
@@ -195,13 +196,15 @@ public abstract class CollectionUtils {
/**
* Check whether the given Iterator contains the given element.
* @param iterator the Iterator to check
* Check whether the given {@link Iterator} contains the given element.
* @param iterator the {@code Iterator} to check
* @param element the element to look for
* @return {@code true} if found, {@code false} otherwise
*/
@Contract("null, _ -> false")
public static boolean contains(@Nullable Iterator<?> iterator, Object element) {
public static boolean contains(@Nullable Iterator<? extends @Nullable Object> iterator,
@Nullable Object element) {
if (iterator != null) {
while (iterator.hasNext()) {
Object candidate = iterator.next();
@@ -214,13 +217,15 @@ public abstract class CollectionUtils {
}
/**
* Check whether the given Enumeration contains the given element.
* @param enumeration the Enumeration to check
* Check whether the given {@link Enumeration} contains the given element.
* @param enumeration the {@code Enumeration} to check
* @param element the element to look for
* @return {@code true} if found, {@code false} otherwise
*/
@Contract("null, _ -> false")
public static boolean contains(@Nullable Enumeration<?> enumeration, Object element) {
public static boolean contains(@Nullable Enumeration<? extends @Nullable Object> enumeration,
@Nullable Object element) {
if (enumeration != null) {
while (enumeration.hasMoreElements()) {
Object candidate = enumeration.nextElement();
@@ -233,15 +238,17 @@ public abstract class CollectionUtils {
}
/**
* Check whether the given Collection contains the given element instance.
* Check whether the given {@link Collection} contains the given element instance.
* <p>Enforces the given instance to be present, rather than returning
* {@code true} for an equal element as well.
* @param collection the Collection to check
* @param collection the {@code Collection} to check
* @param element the element to look for
* @return {@code true} if found, {@code false} otherwise
*/
@Contract("null, _ -> false")
public static boolean containsInstance(@Nullable Collection<?> collection, Object element) {
public static boolean containsInstance(@Nullable Collection<? extends @Nullable Object> collection,
@Nullable Object element) {
if (collection != null) {
for (Object candidate : collection) {
if (candidate == element) {
@@ -255,12 +262,22 @@ public abstract class CollectionUtils {
/**
* Return {@code true} if any element in '{@code candidates}' is
* contained in '{@code source}'; otherwise returns {@code false}.
* @param source the source Collection
* @param source the source {@link Collection}
* @param candidates the candidates to search for
* @return whether any of the candidates has been found
*/
public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
return findFirstMatch(source, candidates) != null;
public static boolean containsAny(Collection<? extends @Nullable Object> source,
Collection<? extends @Nullable Object> candidates) {
if (isEmpty(source) || isEmpty(candidates)) {
return false;
}
for (Object candidate : candidates) {
if (source.contains(candidate)) {
return true;
}
}
return false;
}
/**

View File

@@ -18,10 +18,10 @@ package org.springframework.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -42,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Rob Harrop
* @author Juergen Hoeller
* @author Rick Evans
* @author Sam Brannen
*/
class CollectionUtilsTests {
@@ -100,19 +101,24 @@ class CollectionUtilsTests {
}
@Test
void contains() {
void containsWithIterator() {
assertThat(CollectionUtils.contains((Iterator<String>) null, "myElement")).isFalse();
assertThat(CollectionUtils.contains((Enumeration<String>) null, "myElement")).isFalse();
assertThat(CollectionUtils.contains(new ArrayList<String>().iterator(), "myElement")).isFalse();
assertThat(CollectionUtils.contains(new Hashtable<String, Object>().keys(), "myElement")).isFalse();
assertThat(CollectionUtils.contains(List.of().iterator(), "myElement")).isFalse();
List<String> list = new ArrayList<>();
list.add("myElement");
List<String> list = Arrays.asList("myElement", null);
assertThat(CollectionUtils.contains(list.iterator(), "myElement")).isTrue();
assertThat(CollectionUtils.contains(list.iterator(), null)).isTrue();
}
Hashtable<String, String> ht = new Hashtable<>();
ht.put("myElement", "myValue");
assertThat(CollectionUtils.contains(ht.keys(), "myElement")).isTrue();
@Test
void containsWithEnumeration() {
assertThat(CollectionUtils.contains((Enumeration<String>) null, "myElement")).isFalse();
assertThat(CollectionUtils.contains(Collections.enumeration(List.of()), "myElement")).isFalse();
List<String> list = Arrays.asList("myElement", null);
Enumeration<String> enumeration = Collections.enumeration(list);
assertThat(CollectionUtils.contains(enumeration, "myElement")).isTrue();
assertThat(CollectionUtils.contains(enumeration, null)).isTrue();
}
@Test
@@ -128,39 +134,49 @@ class CollectionUtilsTests {
candidates.add("abc");
assertThat(CollectionUtils.containsAny(source, candidates)).isTrue();
candidates.remove("def");
assertThat(CollectionUtils.containsAny(source, candidates)).isTrue();
candidates.remove("abc");
assertThat(CollectionUtils.containsAny(source, candidates)).isFalse();
source.add(null);
assertThat(CollectionUtils.containsAny(source, candidates)).isFalse();
candidates.add(null);
assertThat(CollectionUtils.containsAny(source, candidates)).isTrue();
}
@Test
void containsInstanceWithNullCollection() {
assertThat(CollectionUtils.containsInstance(null, this)).as("Must return false if supplied Collection argument is null").isFalse();
assertThat(CollectionUtils.containsInstance(null, this)).isFalse();
}
@Test
void containsInstanceWithInstancesThatAreEqualButDistinct() {
List<Instance> list = new ArrayList<>();
list.add(new Instance("fiona"));
assertThat(CollectionUtils.containsInstance(list, new Instance("fiona"))).as("Must return false if instance is not in the supplied Collection argument").isFalse();
List<Instance> list = List.of(new Instance("fiona"));
assertThat(CollectionUtils.containsInstance(list, new Instance("fiona"))).isFalse();
}
@Test
void containsInstanceWithSameInstance() {
List<Instance> list = new ArrayList<>();
list.add(new Instance("apple"));
Instance instance = new Instance("fiona");
list.add(instance);
assertThat(CollectionUtils.containsInstance(list, instance)).as("Must return true if instance is in the supplied Collection argument").isTrue();
Instance fiona = new Instance("fiona");
Instance apple = new Instance("apple");
List<Instance> list = List.of(fiona, apple);
assertThat(CollectionUtils.containsInstance(list, fiona)).isTrue();
}
@Test
void containsInstanceWithNullInstance() {
List<Instance> list = new ArrayList<>();
list.add(new Instance("apple"));
list.add(new Instance("fiona"));
assertThat(CollectionUtils.containsInstance(list, null)).as("Must return false if null instance is supplied").isFalse();
Instance fiona = new Instance("fiona");
List<Instance> list = List.of(fiona);
assertThat(CollectionUtils.containsInstance(list, null)).isFalse();
list = Arrays.asList(fiona, null);
assertThat(CollectionUtils.containsInstance(list, null)).isTrue();
}
@Test
@@ -176,6 +192,13 @@ class CollectionUtilsTests {
candidates.add("abc");
assertThat(CollectionUtils.findFirstMatch(source, candidates)).isEqualTo("def");
source.clear();
source.add(null);
assertThat(CollectionUtils.findFirstMatch(source, candidates)).isNull();
candidates.add(null);
assertThat(CollectionUtils.findFirstMatch(source, candidates)).isNull();
}
@Test