I am writing a method, that is intended to search a nested collection recursively for a value and return the collection, which contains that value:
@SuppressWarnings("unchecked")
public static <E,
R extends Collection<? extends E>> Optional<R> findRecursively(Collection<?> collection, E element)
throws ClassCastException {
if (collection.isEmpty())
return Optional.ofNullable(null);
boolean nested = collection.stream()
.allMatch(e -> isSubclass(e.getClass(), Collection.class));
for (Object c : collection) {
R result;
if (nested) {
Optional<R> recursiveResult = findRecursively((Collection<?>) c, element);
result = recursiveResult.orElse(null);
} else {
result = c.equals(element) ? (R) collection : null;
}
if (result != null)
return Optional.of(result);
}
return Optional.ofNullable(null);
}
This works fine, but when I use that method I cannot work with the returned Optional direktly without giving it to a variable first like this:
Collection<String> collection = null;
Set<String> set = Util.findRecursively(collection, "")
.orElseThrow(RuntimeException::new);
In that case the compiler cannot know the return-type of the method. I don't know any good possibility to make it work.
I figured out 2 other ways, that are not very nice either:
I add a parameter with type of the return-type that should be returned like:
public static <E, R extends Collection<E>> Optional<R> findRecursively(Collection<?> collection, E element, Class<R> returnType) {...
But I don't like this, because the additional parameter is (actually) unnecessary and makes the method less easily understandable.
Instead of an Optional I return just the collection-object. But in that case I cannot create an Optional directly with calling it either like:
Collection<String> collection = null; Set<String> set = Optional.ofNullable(Util.findRecursively(collection, "")) .orElseThrow(RuntimeException::new);
Because here again the compiler doesn't know the return-type and cannot infer the type-arguments to the
of()
method.
Does anybody have any idea of a nice solution for this issue? Or an advise which way to go here?