можно ли привести поток в java 8?

<p>можно ли привести поток в java 8? скажем, у меня есть список объектов, я могу сделать что-то вроде этого, чтобы отфильтровать все дополнительные объекты:</p><pre><code>stream.of(objects).filter(c -> c instanceof client) </code></pre><p>однако после этого, если я хочу что-то сделать с клиентами, мне нужно разыграть каждого из них:</p><pre><code>stream.of(objects).filter(c -> c instanceof client) .map(c -> ((client) c).getid()).foreach(system.out::println); </code></pre><p>это выглядит немного некрасиво. можно ли привести весь поток к другому типу? как приведение <code>stream<object></code> к <code>stream<client></code>?</p><p>пожалуйста, игнорируйте тот факт, что подобные вещи, вероятно, означают плохой дизайн. мы занимаемся такими вещами на моем уроке информатики, поэтому я изучал новые функции java 8 и мне было любопытно, возможно ли это.</p>

<p>я не думаю, что есть способ сделать это из коробки. возможно более чистое решение было бы:</p><pre><code>stream.of(objects) .filter(c -> c instanceof client) .map(c -> (client) c) .map(client::getid) .foreach(system.out::println); </code></pre><p>или, как предлагается в комментариях, вы можете использовать метод <code>cast</code> - первый может быть легче читать, хотя:</p><pre><code>stream.of(objects) .filter(client.class::isinstance) .map(client.class::cast) .map(client::getid) .foreach(system.out::println); </code></pre>

<p>в соответствии с <a href="https://stackoverflow.com/a/23473558/1237044">ответ ggovan</a> , я делаю это следующим образом:</p><pre><code>/** * 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(); } } </code></pre><p>используя эту вспомогательную функцию:</p><pre><code>stream.of(objects).flatmap(f.instancesof(client.class)) .map(client::getid) .foreach(system.out::println); </code></pre>

<p>поздно на вечеринку, но я думаю, что это полезный ответ.</p><p><code>flatmap</code> будет самым коротким способом сделать это.</p><pre><code>stream.of(objects).flatmap(o->(o instanceof client)?stream.of((client)o):stream.empty()) </code></pre><p>если <code>o</code> является <code>client</code>, тогда создайте поток с одним элементом, в противном случае используйте пустой поток. эти потоки будут затем сведены в <code>stream<client></code>.</p>

<blockquote> <p>это выглядит немного некрасиво. можно ли привести весь поток к другому типу? как приведение <code>stream<object></code> к <code>stream<client></code>?</p> </blockquote><p>нет, это было бы невозможно. это не ново в java 8. это относится к универсальным. <code>list<object></code> не является супертипом <code>list<string></code>, поэтому вы не можете просто привести <code>list<object></code> к <code>list<string></code>.</p><p>подобная проблема здесь. вы не можете привести <code>stream<object></code> к <code>stream<client></code>. конечно, вы можете использовать его косвенно следующим образом:</p><pre><code>stream<client> intstream = (stream<client>) (stream<?>)stream; </code></pre><p>но это небезопасно и может дать сбой во время выполнения. основная причина этого заключается в том, что дженерики в java реализованы с использованием стирания. таким образом, нет никакой доступной информации о типе <code>stream</code> во время выполнения. все просто <code>stream</code>.</p><p>кстати, что не так с вашим подходом? выглядит хорошо для меня.</p>