是否有可能在Java 8中投射stream?
是否有可能在Java 8中投射stream? 说我有一个对象列表,我可以做这样的事情来过滤掉所有的附加对象:
Stream.of(objects).filter(c -> c instanceof Client)
在这之后,如果我想和客户做一些事情,我需要把它们中的每一个都投给:
Stream.of(objects).filter(c -> c instanceof Client) .map(c -> ((Client) c).getID()).forEach(System.out::println);
这看起来有点难看。 是否有可能将整个stream转换为不同的types? 像将Stream<Object>
Stream<Client>
转换为Stream<Client>
?
请忽略这样的事实可能意味着不好的devise。 我们在计算机科学课上做这样的东西,所以我正在研究java 8的新特性,并且很好奇这是否可能。
我不认为有一种方法可以做到这一点。 一个可能更干净的解决scheme是:
Stream.of(objects) .filter(c -> c instanceof Client) .map(c -> (Client) c) .map(Client::getID) .forEach(System.out::println);
或者如注释中所build议的那样,您可以使用cast
方法 – 前者可能更容易阅读:
Stream.of(objects) .filter(Client.class::isInstance) .map(Client.class::cast) .map(Client::getID) .forEach(System.out::println);
根据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(); } }
使用这个辅助函数:
Stream.of(objects).flatMap(F.instancesOf(Client.class)) .map(Client::getId) .forEach(System.out::println);
晚会到了,但我认为这是一个有用的答案。
flatMap
将是最短的做法。
Stream.of(objects).flatMap(o->(o instanceof Client)?Stream.of((Client)o):Stream.empty())
如果o
是Client
,则使用单个元素创build一个Stream,否则使用空的stream。 这些stream将被平铺成Stream<Client>
。
这看起来有点难看。 是否有可能将整个stream转换为不同的types? 像将
Stream<Object>
Stream<Client>
转换为Stream<Client>
?
不,这是不可能的。 这在Java 8中并不是新鲜事。这是针对generics的。 List<Object>
不是List<String>
的超types,所以不能只将List<Object>
转换为List<String>
。
类似的问题在这里。 您不能将Stream<Object>
为Stream<Client>
。 当然你可以这样间接地施放它:
Stream<Client> intStream = (Stream<Client>) (Stream<?>)stream;
但这并不安全,在运行时可能会失败。 其根本原因是,Java中的generics是使用擦除来实现的。 因此,在运行时没有关于哪种types的Stream
types信息。 一切都只是Stream
。
顺便说一下,你的方法有什么问题? 对我看起来很好。