Is it possible to cast a Stream in Java 8?

JavaJava 8Java Stream

Java Problem Overview


Is it possible to cast a stream in Java 8? Say I have a list of objects, I can do something like this to filter out all the additional objects:

Stream.of(objects).filter(c -> c instanceof Client)

After this though, if I want to do something with the clients I would need to cast each of them:

Stream.of(objects).filter(c -> c instanceof Client)
    .map(c -> ((Client) c).getID()).forEach(System.out::println);

This looks a little ugly. Is it possible to cast an entire stream to a different type? Like cast Stream<Object> to a Stream<Client>?

Please ignore the fact that doing things like this would probably mean bad design. We do stuff like this in my computer science class, so I was looking into the new features of java 8 and was curious if this was possible.

Java Solutions


Solution 1 - Java

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);

Solution 2 - Java

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);

Solution 3 - Java

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>.

Solution 4 - Java

> This looks a little ugly. Is it possible to cast an entire stream to a different type? Like cast Stream<Object> to a Stream<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.

Solution 5 - Java

I found when dealing with an untyped collection of one class you can create a typed collection with

UntypedObjCollection bag = some preGenerics method;
List<Foo> foolist = new ArrayList<>();
bag.stream().forEach(o ->fooList.add((Foo)o));

There doesn't seem to be a way to cast Object into something and filter, map, etc... in one shot. The only way to get Object into a typed collection is a terminal operation. This is running JDK 17 and dealing with module.base exceptions when trying less granular methods.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPhictionView Question on Stackoverflow
Solution 1 - JavaassyliasView Answer on Stackoverflow
Solution 2 - JavaBrandonView Answer on Stackoverflow
Solution 3 - JavaggovanView Answer on Stackoverflow
Solution 4 - JavaRohit JainView Answer on Stackoverflow
Solution 5 - JavaSherumView Answer on Stackoverflow