Czy Collection.stream (). Filter (). ForEach () jest nieefektywny w porównaniu ze standardem dla każdej pętli?

15

IntelliJ IDEA polecił mi właśnie teraz, aby zastąpić następującą pętlę dla każdej z wywołań Java 8 „forEach”:

    for (Object o : objects) {
        if (o instanceof SomeObject) {
            doSomething();
        }
    }

Zalecane połączenie wygląda następująco:

objects.stream().filter(o -> o instanceof SomeObject).forEach(o -> doSomething());

O ile nie rozumiem, jak działa podstawowa funkcjonalność Stream, wydaje mi się, że użycie stream jest operacją O (2n) w przeciwieństwie do operacji O (n) dla standardowej pętli dla każdej pętli.

Mirrana
źródło
8
Jak myślisz, dlaczego to jest O ^ 2? W rzeczywistości strumienie zostały wymyślone specjalnie, aby (a) umożliwić lepszą składnię i (b) nie wprowadzać dodatkowego obciążenia. (W rzeczywistości często zmniejszają koszty ogólne poprzez leniwą ocenę.)
Kilian Foth
Opierając się na składni, wygląda na to, że najpierw iteruje się w celu filtrowania, a następnie iteruje po filtrowanych obiektach po raz drugi, aby uruchomić mój kod.
Mirrana
6
Nawet gdyby tak się stało, nadal byłby to O (2 * N), który jest O (N), tj. Liniowy i nie kwadratowy. Ale tak naprawdę iteracje są ze sobą przeplatane i oba mogą zakończyć się wcześniej, jeśli wynik jest już znany - takie jest piękno strumieni. Zdecydowanie warto poświęcić 15 minut na czytanie strumieni w Javie 8; jak pisze Venkat Subramaniam: „Wyrażenia lambda są bramą do Java 8, ale strumienie są prawdziwym uzależnieniem.”
Kilian Foth
1
Poza tym: twoja pętla jest antypatternem;)
Thomas Junk
1
@ThomasJunk Czy możesz wyjaśnić, jak to jest antypattern? Nie znam tego.
Mirrana

Odpowiedzi:

21

Strumienie Java nie iterują Twojej kolekcji raz dla każdej instrukcji, pomimo tego, co sugeruje składnia. Stosuje cały łańcuch do każdego elementu, po jednym elemencie na raz.

W twoim przypadku strumień działałby dokładnie tak jak pętla. Weź element, sprawdź go względem predykatu, a następnie zastosuj operację, a następnie przejdź do następnego elementu.

Rosa Richter
źródło