Czy można przesyłać strumień w Javie 8? Powiedzmy, że mam listę obiektów, mogę zrobić coś takiego, aby odfiltrować wszystkie dodatkowe obiekty:
Stream.of(objects).filter(c -> c instanceof Client)
Po tym jednak, jeśli chcę coś zrobić z klientami, musiałbym obsadzić każdego z nich:
Stream.of(objects).filter(c -> c instanceof Client)
.map(c -> ((Client) c).getID()).forEach(System.out::println);
To wygląda trochę brzydko. Czy można rzucić cały strumień na inny typ? Jak rzucać Stream<Object>
do Stream<Client>
?
Proszę zignorować fakt, że robienie takich rzeczy prawdopodobnie oznaczałoby zły projekt. Robimy takie rzeczy na moich zajęciach z informatyki, więc szukałem nowych funkcji java 8 i byłem ciekawy, czy to jest możliwe.
java
java-8
java-stream
Fikcja
źródło
źródło
Odpowiedzi:
Nie sądzę, aby można było to zrobić po wyjęciu z pudełka. Prawdopodobnie czystszym rozwiązaniem byłoby:
lub, jak sugerowano w komentarzach, możesz skorzystać z
cast
metody - ta pierwsza może być jednak łatwiejsza do odczytania:źródło
map
zwróciłoby plikStream<Client>
. Dzięki!Stream.of(objects).filter(Client.class::isInstance).[...]
Zgodnie z odpowiedzią ggovana , robię to w następujący sposób:
Korzystanie z tej funkcji pomocniczej:
źródło
Spóźniłem się na imprezę, ale myślę, że to przydatna odpowiedź.
flatMap
byłby to najkrótszy sposób.Jeśli
o
jestClient
to, utwórz Stream z jednym elementem, w przeciwnym razie użyj pustego strumienia. Te strumienie zostaną następnie spłaszczone do plikuStream<Client>
.źródło
if/else
zamiast?:
operatora, nie byłoby ostrzeżenia. Zapewniamy, że możesz bezpiecznie usunąć ostrzeżenie.Stream.of(objects).filter(o->o instanceof Client).map(o -> (Client)o)
lub nawetStream.of(objects).filter(Client.class::isInstance).map(Client.class::cast)
.Nie, to nie byłoby możliwe. Nie jest to nowość w Javie 8. Jest to specyficzne dla typów ogólnych. A
List<Object>
nie jest super typemList<String>
, więc nie możesz po prostu rzucić aList<Object>
naList<String>
.Podobnie jest w tym przypadku. Nie można rzucać
Stream<Object>
sięStream<Client>
. Oczywiście możesz rzucić to pośrednio w ten sposób:ale to nie jest bezpieczne i może zawieść w czasie wykonywania. Przyczyną tego jest to, że generyczne w Javie są implementowane przy użyciu wymazywania. Tak więc nie ma dostępnych informacji o typie, który typ
Stream
jest w czasie wykonywania. Wszystko jest sprawiedliweStream
.A tak przy okazji, co jest nie tak z twoim podejściem? Dla mnie wygląda dobrze.
źródło
C#
jest implementowane przy użyciu reifikacji, podczas gdy w Javie jest zaimplementowane za pomocą erasure. Oba są realizowane w różny sposób. Nie możesz więc oczekiwać, że będzie działać tak samo w obu językach.