Вы можете легко сделать это более свободно, полагаясь на методы map()
/ flatMap()
и cast
, которые вместо этого возвращают функции.
Для Optional
это очень просто, поскольку map()
может выступать в качестве фильтра, возвращая null
. Так что просто определите:
public static <U> Function<Object, U> filterAndCast(Class<? extends U> clazz) {
return t -> clazz.isInstance(t) ? clazz.cast(t) : null;
}
и используйте его как:
Optional<Number> number = Optional.of(42L);
System.out.println(number.map(filterAndCast(Integer.class)));
System.out.println(number.map(filterAndCast(Long.class)));
Выход:
Optional.empty
Optional[42]
Для потоков вы можете применить более или менее тот же трюк, полагаясь на flatMap()
с функцией, которая возвращает пустое Stream
:
public static <U> Function<Object, Stream<U>> streamFilterAndCast(Class<? extends U> clazz) {
return t -> clazz.isInstance(t) ? Stream.of(clazz.cast(t)) : Stream.empty();
// or alternatively
return t -> Stream.of(t).filter(clazz::isInstance).map(clazz::cast);
}
и используйте его как:
Stream.of(42L, "Hello world", 1024, 3.14)
.flatMap(streamFilterAndCast(Number.class))
.forEach(System.out::println);
Выход:
42
1024
3.14