Est-il possible de lancer un flux dans Java 8? Disons que j'ai une liste d'objets, je peux faire quelque chose comme ceci pour filtrer tous les objets supplémentaires:
Stream.of(objects).filter(c -> c instanceof Client)
Après cela, si je veux faire quelque chose avec les clients, j’ai besoin de lancer chacun d’eux:
Stream.of(objects).filter(c -> c instanceof Client)
.map(c -> ((Client) c).getID()).forEach(System.out::println);
Cela semble un peu moche. Est-il possible de convertir un flux entier dans un type différent? Comme cast Stream<Object>
en Stream<Client>
?
Ignorez s'il vous plaît le fait que de telles choses signifieraient probablement une mauvaise conception. Nous faisons ce genre de choses dans mon cours d'informatique. J'étais donc à la recherche des nouvelles fonctionnalités de Java 8 et étais curieux de savoir si cela était possible.
Je ne pense pas qu'il y ait un moyen de faire ça tout de suite. Une solution éventuellement plus propre serait:
Stream.of(objects)
.filter(c -> c instanceof Client)
.map(c -> (Client) c)
.map(Client::getID)
.forEach(System.out::println);
ou, comme suggéré dans les commentaires, vous pouvez utiliser la méthode cast
- la première peut être plus facile à lire, cependant:
Stream.of(objects)
.filter(Client.class::isInstance)
.map(Client.class::cast)
.map(Client::getID)
.forEach(System.out::println);
Dans le sens de réponse de ggovan , je le fais comme suit:
/**
* 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();
}
}
En utilisant cette fonction d'assistance:
Stream.of(objects).flatMap(F.instancesOf(Client.class))
.map(Client::getId)
.forEach(System.out::println);
En retard à la fête, mais je pense que c'est une réponse utile.
flatMap
serait le moyen le plus court de le faire.
Stream.of(objects).flatMap(o->(o instanceof Client)?Stream.of((Client)o):Stream.empty())
Si o
est un Client
, créez un Stream avec un seul élément, sinon utilisez le flux vide. Ces flux seront ensuite aplatis dans un Stream<Client>
.
Cela semble un peu moche. Est-il possible de convertir un flux entier dans un type différent? Comme cast
Stream<Object>
enStream<Client>
?
Non, ce ne serait pas possible. Ce n'est pas nouveau dans Java 8. Ceci est spécifique aux génériques. Un List<Object>
n'est pas un super type de List<String>
, vous ne pouvez donc pas simplement convertir un List<Object>
en List<String>
.
Le problème est similaire ici. Vous ne pouvez pas convertir Stream<Object>
en Stream<Client>
. Bien sûr, vous pouvez le lancer indirectement comme ceci:
Stream<Client> intStream = (Stream<Client>) (Stream<?>)stream;
mais ce n'est pas sûr et peut échouer au moment de l'exécution. La raison sous-jacente à cela est que les génériques dans Java sont implémentés à l’aide de erasure. Donc, il n'y a aucune information de type disponible sur le type de Stream
qu'il est au moment de l'exécution. Tout est juste Stream
.
BTW, quel est le problème avec votre approche? Ca me va.