Spotkałem się ostatnio z pytaniem czemu jak chcemy działać na stream ach to musimy na naszej dajmy na to liście wywołać 'stream()' i dopiero później przejść do właściwej części np, forEach/ map etc. Pytanie -> czemu na samej korelacji nie można od razu wywoływać tych metod co na streamach. forEcha/map etc. Nie mogę nigdzie znaleźć odpowiedzi. Słyszałem także o jakimś frameworku, który to umożliwia ale nie pamiętam nazwy.

- Rejestracja:około 21 lat
- Ostatnio:prawie 3 lata
- Lokalizacja:Space: the final frontier
- Postów:26433
korelacji
kolekcji...
A co do reszty to nie bardzo rozumiem pytanie. Chcesz wiedzieć czemu nie wrzucono wszystkich streamowych metod bezpośrednio do kolekcji? Po pierwsze byłoby to mocno nieeleganckie i łamało SRP, a po drugie, co ważniejsze, streamy są lazy. Operacje na elementach strumienia są wykonywane dopiero kiedy trzeba, kiedy masz jakąś terminalną operacje. Gdyby nie było Stream<T>
i wszystkie te metody były upchane w Collection<T>
to te .map()
czy .filter()
musiałyby zwracać faktyczne kolekcje, czyli tym samym ewaluować wszystko od razu.
Przy czym akurat .forEach()
możesz wołać bezpośrednio na kolekcji bo to i tak operacja terminalna.
Nie wspominając o tym że:
- na kolekcji oprócz
stream()
można zrobićpararellStream()
co zrównolegli potencjalne operacje - można zrobić stream nie na podstawie kolekcji, np
Stream.of()
. - streamy po funkcji terminującej (
collect()
,findFirst()
,anyMatch()
) jest w stanie "closed" i nie można na nim już nic zawołać.

- Rejestracja:ponad 6 lat
- Ostatnio:5 dni
- Lokalizacja:Silesia/Marki
- Postów:5505
Dlaczego tak zrobili? Bo Java ma już 25 lat i trudno wprowadzać nowe feature bez łamania starego api.
A może programiści Javy są głupsi (sam zawodowo programuję w Javie) i jakby kolekcje miały metody map/filter, ale działające zachłannie to nikt nie używał by leniwych wersji ze Streamów ? Bo np nikt by nie przeczytał dokumentacji. Wcale by mnie to nie zdziwiło
Jak wyglądają inne rozwiązania na JVM?
- W Scali wybrali podejście, że słowo kluczowe
lazy
decyduje że operacja mą być odroczone (są leniwe) czy wykonać się natychmiast (są zachłanne) - W Kotlinie także dali wybór. Normalny map/filter wykonuje się zachłannie, a jak chcemy leniwie to trzeba przekonwertować kolekcję na
Sequence
(odpowiednikStream
z Javy) - W Vavrze mamy i klasę
Lazy
i leniwyStream
i zachłanne map/filter w normalnych kolekcjach, czyli ogólnie hulaj dusza piekła nie ma - W Clojurze kolekcje zawsze są leniwe, ale to Lisp i to w dodatku inspirowany Haskellem
- W języku Eta, wszystko domyślnie jest leniwe, ale to już prawdziwy Haskell

lazy
w scali znam tylko jako lazy val
, a jeśli chodzi o standardowe kolekcje, to jest jak w vavr, większość eager, ale są leniwe widoki - czyli jak Stream.

lazy val output2 = geeks.map(l=> l*2)
i nazwali to lazy evaluation
dla kolekcji. Oczywiście nieskończonego streama się tak nie zrobi. W zasadzie jak na to patrze po przespanej nocy to to duże go sensu nie ma :P
Shalom.stream()
jest znikomy, a szansa że ktoś błędnie będzie robił eager ewaluacje bezpośrednio na kolekcji jest spora. Ba, zgaduje że pewnie > 75% programistów nawet nie pomyśli o tym że temap
czyfilter
na vavrowej kolekcji są eager ;]Shalom.map().map().map().collect()
traversuje strumień raz robiącf(g(h(x)))
a robienie tego na kolekcji trawersuje wszystko tyle razy ile masz tychmap
po drodze, aplikując funkcje po jednej.