Java 8 offers the possibility to create streams out of three primitive types: int, long and double. As Stream<T> is a generic interface, and there is no way to use primitives as a type parameter with generics, three new special interfaces were created: IntStream, LongStream, DoubleStream.
Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result.
Since JDK 8, a spliterator method has been included in every collection, so Java Streams use the Spliterator internally to iterate through the elements of a Stream. Java provides implementations of the Spliterator interface, but you can provide your own implementation of Spliterator if for whatever reason you need it.
I don't think there is a way to do that out-of-the-box. A possibly cleaner solution would be:
Stream.of(objects)
.filter(c -> c instanceof Client)
.map(c -> (Client) c)
.map(Client::getID)
.forEach(System.out::println);
or, as suggested in the comments, you could use the cast
method - the former may be easier to read though:
Stream.of(objects)
.filter(Client.class::isInstance)
.map(Client.class::cast)
.map(Client::getID)
.forEach(System.out::println);
Along the lines of ggovan's answer, I do this as follows:
/**
* 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();
}
}
Using this helper function:
Stream.of(objects).flatMap(F.instancesOf(Client.class))
.map(Client::getId)
.forEach(System.out::println);
Late to the party, but I think it is a useful answer.
flatMap
would be the shortest way to do it.
Stream.of(objects).flatMap(o->(o instanceof Client)?Stream.of((Client)o):Stream.empty())
If o
is a Client
then create a Stream with a single element, otherwise use the empty stream. These streams will then be flattened into a Stream<Client>
.
This looks a little ugly. Is it possible to cast an entire stream to a different type? Like cast
Stream<Object>
to aStream<Client>
?
No that wouldn't be possible. This is not new in Java 8. This is specific to generics. A List<Object>
is not a super type of List<String>
, so you can't just cast a List<Object>
to a List<String>
.
Similar is the issue here. You can't cast Stream<Object>
to Stream<Client>
. Of course you can cast it indirectly like this:
Stream<Client> intStream = (Stream<Client>) (Stream<?>)stream;
but that is not safe, and might fail at runtime. The underlying reason for this is, generics in Java are implemented using erasure. So, there is no type information available about which type of Stream
it is at runtime. Everything is just Stream
.
BTW, what's wrong with your approach? Looks fine to me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With