I have a trimmed down version of my code to illustrate the issue.
Here’s the compilation error I’m getting:
The method anyMatch(Predicate<? super capture#26-of ?>) in the type Stream<capture#26-of ?> is not applicable for the arguments (Predicate<Map<?,?>>)
My code:
private void func(Object o) { Predicate<Map<?, ?>> pred = m -> true; if (o instanceof Map && pred.test((Map<?, ?>) o)) { // ...pred.test is OK } else if (o instanceof Collection && ((Collection<?>) o).stream().filter(i -> i instanceof Map).anyMatch(pred)) { // ...anyMatch here gives the above error } }
How would you fix the code to remove the error? Thank you!
Advertisement
Answer
The fact that you have applied instanceof
check in the filter()
doesn’t change the type of the stream, it remains to be Stream<Object>
.
filter()
operation is meant for discarding elements from the stream, not for modifying the elements, therefore it’s not capable of changing the type of the stream.
To perform modifications, you need to apply map()
operation and either use conversion via type cast or method Class.cast()
:
.<Map<?,?>>map(Map.class::cast)
or
.map(i -> (Map<?, ?>) i)
Alternatively, you can leverage Java 16 Pattern matching for instanceof combining both filter
and map
in one step by making use of mapMulty()
which was also introduced with Java 16:
((Collection<?>) o).stream() .<Map<?,?>>mapMulti((i, consumer) -> { if (i instanceof Map m) consumer.accept(m); }) .anyMatch(pred)
Note
It is worth to point out that the whole problem derived from the way the method is designed. By making it accept an argument of type java.lang.Object
you’re forced to operate via type-checking and casting.
A more maintainable approach would to try to leverage generic types, potentially it might lead to splitting this method into several methods (or introducing a few auxiliary methods). But if it would be the case it’s not a disadvantage, leaner method easier to digest, and it’s less error-prone.
Also, worth reminding that if you have multiple pieces of functionality performing unrelated things packed together, it’s probably a violation of the first principle of SOLID.
As the sidenote, from the perspective of clean-coding I would not advise placing a stream into the if
-statement, especially containing multiple operation. Alternative: extract this logic, give it a name, explaining what it does, and refer to it via method call or Predicate