Dlaczego Stream nie implementuje Iterowalnego?
W Javie 8 mamy klasę Stream
Iterator<T> iterator()
Więc można oczekiwać, że zaimplementuje interfejs Iterable
Kiedy chcę iterować nad strumieniem za pomocą pętli foreach, muszę zrobić coś w stylu
public static Iterable<T> getIterable(Stream<T> s) {
return new Iterable<T> {
@Override
public Iterator<T> iterator() {
return s.iterator();
}
};
}
for (T element : getIterable(s)) { ... }
Czy coś mi umknęło? 9 answers
Są już osoby pytane o to samo na liście dyskusyjnej ☺. Głównym powodem jest Iterable ma również re-iterable semantic, podczas gdy Stream nie jest.
Myślę, że głównym powodem jest to, że
Iterable
implikuje możliwość ponownego użycia, podczas gdyStream
jest czymś, co może być użyte tylko raz - bardziej jakIterator
.Jeśli
Stream
RozszerzonyIterable
wtedy istniejący kod może być zaskoczony, gdy otrzymaIterable
, który rzucaException
drugi raz robiąfor (element : iterable)
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-21 19:26:45
Aby przekonwertować Stream
na Iterable
, możesz wykonać
Stream<X> stream = null;
Iterable<X> iterable = stream::iterator
Aby przekazać Stream
do metody, która oczekuje Iterable
,
void foo(Iterable<X> iterable)
Po prostu
foo(stream::iterator)
Jednak prawdopodobnie wygląda to śmiesznie; może lepiej być trochę bardziej wyraźne
foo( (Iterable<X>)stream::iterator );
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-08 21:12:42
Chciałbym zwrócić uwagę, że StreamEx
implementuje Iterable
(i Stream
), a także wiele innych niezmiernie niesamowitych funkcji, których brakuje w Stream
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-30 16:16:47
Kennytm opisał dlaczego jest niebezpieczne traktowanie {[1] } jako Iterable
, a Zhong Yu zaoferował obejście , które pozwala na używanie Stream
Jak w Iterable
, aczkolwiek w sposób niebezpieczny. Możliwe jest uzyskanie tego, co najlepsze z obu światów: wielokrotnego użytku Iterable
z Stream
, który spełnia wszystkie gwarancje zawarte w specyfikacji Iterable
.
Uwaga: SomeType
nie jest tu parametrem typu-należy go zastąpić odpowiednim typem (np. odbicie
Stream<SomeType> stream = ...;
Iterable<SomeType> iterable = stream.collect(toList()):
Jest jedna zasadnicza wada:
Korzyści płynące z leniwej iteracji zostaną utracone. Jeśli planujesz natychmiast iterować wszystkie wartości w bieżącym wątku, wszelkie koszty ogólne będą znikome. Jeśli jednak planujesz iterację tylko częściowo lub w innym wątku, ta natychmiastowa i kompletna iteracja może mieć niezamierzone konsekwencje.
Dużą zaletą jest oczywiście to, że możesz ponownie użyć Iterable
, podczas gdy (Iterable<SomeType>) stream::iterator
pozwoli tylko jednorazowego użytku. Jeśli otrzymujący kod będzie wielokrotnie powtarzał kolekcję, jest to nie tylko konieczne, ale prawdopodobnie korzystne dla wydajności.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-30 16:25:01
Możesz użyć strumienia w pętli for
w następujący sposób:
Stream<T> stream = ...;
for (T x : (Iterable<T>) stream::iterator) {
...
}
(Uruchom Ten fragment tutaj)
(używa interfejsu funkcjonalnego Java 8 cast.)
(jest to omówione w niektórych komentarzach powyżej (np.Aleksandr Dubinsky ), ale chciałem wyciągnąć to w odpowiedzi, aby było bardziej widoczne.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-27 10:09:15
Jeśli nie masz nic przeciwko użyciu bibliotek stron trzecich cyclops-react definiuje strumień, który implementuje zarówno Stream, jak i Iterable i jest również odtwarzalny (rozwiązując problem opisany przez kennytma ).
Stream<String> stream = ReactiveSeq.of("hello","world")
.map(s->"prefix-"+s);
Lub:-
Iterable<String> stream = ReactiveSeq.of("hello","world")
.map(s->"prefix-"+s);
stream.forEach(System.out::println);
stream.forEach(System.out::println);
[Disclosure I am the lead developer of cyclops-react]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:23
Nie idealne, ale będzie działać:
iterable = stream.collect(Collectors.toList());
Nie jest idealny, ponieważ pobiera wszystkie przedmioty ze strumienia i umieszcza je w tym List
, co nie jest dokładnie tym, o czym są Iterable
i Stream
. Mają być leniwi .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-07 04:47:48
Możesz iterować wszystkie pliki w folderze używając Stream<Path>
w następujący sposób:
Path path = Paths.get("...");
Stream<Path> files = Files.list(path);
for (Iterator<Path> it = files.iterator(); it.hasNext(); )
{
Object file = it.next();
// ...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-23 21:12:37
Stream
nie implementuje Iterable
. Ogólne zrozumienie Iterable
jest wszystkim, co może być powtarzane, często raz po raz. Stream
może nie być odtwarzane.
Jedynym obejściem, jakie przychodzi mi do głowy, gdy iterowalny strumień oparty na strumieniu jest również odtwarzalny, jest odtworzenie strumienia. Używam Supplier
poniżej, aby utworzyć nową instancję stream, za każdym razem, gdy tworzony jest nowy iterator.
Supplier<Stream<Integer>> streamSupplier = () -> Stream.of(10);
Iterable<Integer> iterable = () -> streamSupplier.get().iterator();
for(int i : iterable) {
System.out.println(i);
}
// Can iterate again
for(int i : iterable) {
System.out.println(i);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-21 05:40:24