是否可以在 Java 8 中转换 Stream?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22511750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:09:56  来源:igfitidea点击:

Is it possible to cast a Stream in Java 8?

javajava-8java-stream

提问by Phiction

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:

是否可以在 Java 8 中转换流?假设我有一个对象列表,我可以执行以下操作来过滤掉所有其他对象:

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

这看起来有点难看。是否可以将整个流转换为不同的类型?喜欢强制Stream<Object>转换为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 8 的新特性,并很好奇这是否可能。

采纳答案by assylias

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 castmethod - the former may be easier to read though:

或者,正如评论中所建议的那样,您可以使用该cast方法-尽管前者可能更易于阅读:

Stream.of(objects)
    .filter(Client.class::isInstance)
    .map(Client.class::cast)
    .map(Client::getID)
    .forEach(System.out::println);

回答by Rohit Jain

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

这看起来有点难看。是否可以将整个流转换为不同的类型?喜欢强制Stream<Object>转换为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>.

不,那是不可能的。这在 Java 8 中并不新鲜。这是泛型特有的。AList<Object>不是 的超类型List<String>,因此您不能将 a 强制转换List<Object>为 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<Object>Stream<Client>. 当然,您可以像这样间接投射它:

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 Streamit is at runtime. Everything is just Stream.

但这并不安全,并且可能在运行时失败。其根本原因是,Java 中的泛型是使用擦除实现的。因此,Stream在运行时没有关于它是哪种类型的类型信息。一切都只是Stream

BTW, what's wrong with your approach? Looks fine to me.

顺便说一句,你的方法有什么问题?对我来说看起来不错。

回答by ggovan

Late to the party, but I think it is a useful answer.

聚会迟到了,但我认为这是一个有用的答案。

flatMapwould be the shortest way to do it.

flatMap将是做到这一点的最短方法。

Stream.of(objects).flatMap(o->(o instanceof Client)?Stream.of((Client)o):Stream.empty())

If ois a Clientthen create a Stream with a single element, otherwise use the empty stream. These streams will then be flattened into a Stream<Client>.

如果oClient,则使用单个元素创建一个流,否则使用空流。然后这些流将被展平成一个Stream<Client>.

回答by Brandon

Along the lines of ggovan's answer, I do this as follows:

沿着ggovan 的回答,我这样做如下:

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