Можно ли использовать Stream в Java 8?
Можно ли создать поток в Java 8? Скажем, у меня есть список объектов, я могу сделать что-то вроде этого, чтобы отфильтровать все дополнительные объекты:
Stream.of(objects).filter(c -> c instanceof Client)
После этого, хотя, если я хочу что-то сделать с клиентами, мне нужно будет отбросить каждую из них:
Stream.of(objects).filter(c -> c instanceof Client)
.map(c -> ((Client) c).getID()).forEach(System.out::println);
Это выглядит немного уродливо. Можно ли передать весь поток другому типу? Как литье Stream<Object>
в Stream<Client>
?
Пожалуйста, проигнорируйте тот факт, что делать подобные вещи, вероятно, означало бы плохой дизайн. Мы делаем такие вещи в моем классе компьютерных наук, поэтому я изучал новые функции java 8 и мне было любопытно, если бы это было возможно.
Ответы
Ответ 1
Я не думаю, что есть способ сделать это из коробки. Возможно, более чистое решение будет:
Stream.of(objects)
.filter(c -> c instanceof Client)
.map(c -> (Client) c)
.map(Client::getID)
.forEach(System.out::println);
или, как предложено в комментариях, вы можете использовать метод cast
- первый может быть легче читать:
Stream.of(objects)
.filter(Client.class::isInstance)
.map(Client.class::cast)
.map(Client::getID)
.forEach(System.out::println);
Ответ 2
Вдоль строк ggovan answer, я делаю это следующим образом:
/**
* Provides various high-order functions.
*/
public final class F {
/**
* When the returned {@code Function} is passed as an argument to
* {@link Stream#flatMap}, the result is a stream of instances of
* {@code cls}.
*/
public static <E> Function<Object, Stream<E>> instancesOf(Class<E> cls) {
return o -> cls.isInstance(o)
? Stream.of(cls.cast(o))
: Stream.empty();
}
}
Используя эту вспомогательную функцию:
Stream.of(objects).flatMap(F.instancesOf(Client.class))
.map(Client::getId)
.forEach(System.out::println);
Ответ 3
Поздно к партии, но я думаю, что это полезный ответ.
flatMap
будет самым коротким способом сделать это.
Stream.of(objects).flatMap(o->(o instanceof Client)?Stream.of((Client)o):Stream.empty())
Если o
- это Client
, тогда создайте Stream с одним элементом, иначе используйте пустой поток. Эти потоки затем будут сплющены в Stream<Client>
.
Ответ 4
Это выглядит немного уродливо. Можно ли передать весь поток другому типу? Как литье Stream<Object>
в Stream<Client>
?
Нет, это было бы невозможно. Это не ново в Java 8. Это характерно для дженериков. A List<Object>
не является супер-типом List<String>
, поэтому вы не можете просто отличить List<Object>
от List<String>
.
Аналогичная проблема здесь. Вы не можете отбрасывать Stream<Object>
до Stream<Client>
. Конечно, вы можете сделать это косвенно следующим образом:
Stream<Client> intStream = (Stream<Client>) (Stream<?>)stream;
но это небезопасно и может выйти из строя во время выполнения. Основная причина этого заключается в том, что генерические средства на Java реализованы с использованием стирания. Таким образом, информация о типе недоступна, какой тип Stream
находится во время выполнения. Все просто Stream
.
Кстати, что случилось с вашим подходом? Выглядит хорошо для меня.