1. Overview
In this tutorial, we’ll explore how to detect null or empty Strings in a List<String> in Java. We’ll start with a classic for-loop that checks each element explicitly, so we understand the mechanics and edge cases. Then we’ll move on to a modern Stream approach that keeps code concise and expressive.
2. for Loop Check
Throughout the code, we’ll use the following example List:
List<String> list = Arrays.asList("Madrid", null, " ", "Havana", "");
Let’s start with a for loop:
@Test
void givenListWithNullOrEmpty_whenCheckForNullOrEmptyUsingForLoop_thenReturnTrue() {
boolean hasNullOrEmpty = false;
for (String s : list) {
if (s == null || s.isEmpty()) {
hasNullOrEmpty = true;
break;
}
}
assertTrue(hasNullOrEmpty, "List should contain null or empty elements");
}
The for-loop iterates through the List in order and checks each element. For every element, we first check the nullability. If it’s not null, we call the isEmpty() method. If we find a null or empty String, we stop and set the result to true. This avoids scanning the entire List when it finds an early match.
This solution runs in O(n) time and uses O(1) space. It’s explicit and easy to debug. Note that isEmpty() treats ” “ as non-empty; we can handle that case using the isBlank() method.
3. Using Stream
Now, let’s implement the same check with Streamin one line:
@Test
void givenListWithNullOrEmpty_whenCheckForNullOrEmptyUsingStreams_thenReturnTrue() {
boolean hasNullOrEmpty = list.stream()
.anyMatch(s -> s == null || s.isEmpty());
assertTrue(hasNullOrEmpty, "List should contain null or blank elements");
}
In this approach, we turn the List into a Stream. We then use anyMatch() with a predicate that checks null first, and then isEmpty(). The anyMatch() method stops at the first match. As a result, the Stream doesn’t always process every element.
This solution runs in O(n) time and uses O(1) space. This version makes the intent clear in just one line.
We can also check for null or empty String using a parallel Stream:
@Test
void givenListWithNullOrEmpty_whenCheckUsingParallelStream_thenReturnTrue() {
boolean hasNullOrEmpty = list.parallelStream()
.anyMatch(s -> s == null || s.isEmpty());
assertTrue(hasNullOrEmpty, "List should contain null or empty elements");
}
Parallel Stream splits the work across multiple cores. The logic stays the same, but processing happens in parallel. As we can see, parallel streams are best for large datasets. For small Lists, a regular Stream is usually faster.
4. Conclusion
In this article, we explored how to detect null or empty String in a List<String> in Java. We saw a for-loop that checks each element (check null first, then isEmpty()) and stops on the first match. We also looked at a Stream solution that uses anyMatch() with isEmpty() to express the same check in one line.
Both approaches run in O(n) time and use O(1) space.
As always, the source code is available over on GitHub.