Is it possible to cast a Stream in Java 8?

后端 未结 4 1913
迷失自我
迷失自我 2020-12-02 08:26

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(obj         


        
相关标签:
4条回答
  • 2020-12-02 08:32

    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);
    
    0 讨论(0)
  • 2020-12-02 08:37

    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.

    0 讨论(0)
  • 2020-12-02 08:42

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

    0 讨论(0)
  • 2020-12-02 08:49

    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);
    
    0 讨论(0)
提交回复
热议问题