1

I have a Map<String, ? extends Collection<SomeClass>>. I would like to ensure that there are no entries where collection's size is 0. Therefore I tried myMap.values().stream().map(Collection::size).allMatch(size -> size > 0). However, as it turned out, myMap contains null entries.

I wanted to check if my map contains null entries: resourceMap.values().stream().noneMatch(null) but I got an Exception java.util.Objects.requireNonNull.

I decided to do it in a relatively old fashioned way, with a for-in loop for (Map.Entry<String, ? extends Collection> entry : myMap) However, I got a compilation error telling me that foreach is not applicable to my Map.

What is an elegant way to check if all entries in my map are not null and with size > 0?

3
  • .map(CollectionUtils::isNotEmpty) from commons-lang Commented Aug 7, 2017 at 17:15
  • 1
    Please show your for each ;) Commented Aug 7, 2017 at 17:15
  • 2
    For map you should use map.entrySet() and then iterate on map entry objects. Commented Aug 7, 2017 at 17:18

2 Answers 2

6

You can just check for nulls using myMap.values().contains(null)—no Stream API required.

If your map was consistently using List or Set, you could also check for empty values with myMap.values().contains(Collections.emptySet()) or myMap.values().contains(Collections.emptyList()), but since there is no general equality contract between arbitrary collections, that doesn’t work for your Map<String, ? extends Collection<SomeClass>>.

So for this specific test, you could use

boolean violations = myMap.values().contains(null) || myMap.values().stream().anyMatch(Collection::isEmpty); 

or

boolean violations = myMap.values().stream().anyMatch(col -> col==null || col.isEmpty()); 

When you want to iterate with a for loop, you have to specify a Collection view over the Map, e.g.

Map<String, ? extends Collection<SomeClass>> myMap; … for (Map.Entry<String, ? extends Collection<?>> entry: myMap.entrySet()) // loop body 

or, much better for this use case

for(Collection<?> value: myMap.values()) if(value == null || value.isEmpty()) // violation detected, perform your action 
Sign up to request clarification or add additional context in comments.

Comments

3

If you have a look at the actual method signature:

boolean noneMatch(Predicate<? super T> predicate) 

You will see that noneMatch(null) accepts a Predicate instance and not an actual value. Null predicates are forbidden here.

Try:

boolean result = resourceMap.values().stream() .noneMatch(Objects::isNull) 

You can merge those two into one chain:

myMap.values().stream() .allMatch(col -> col != null && col.size() > 0); 

4 Comments

Thank you! I cannot combine it, as then if my map contains null entries, but the non-null ones have size > 0 it would evaluate to true. I will just conjunct them with classic &&.
@3yakuya sure, I get it now. I think it's doable to use one stream for that. Let me try.
@3yakuya you can simply .allMatch(col -> col != null && col.size() > 0);
Nice! Thank you!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.