Strumienie

Masz serdecznie dosyć ciągłego iterowania po kolekcjach? Do tego te wszystkie warunki ograniczające… ileż można. Świetnie się jednak składa, dzisiaj pokażę Ci alternatywne rozwiązanie w operowaniu na zbiorach. Zapraszam do lektury.

Czym są strumienie?

Z angielskiego stream zostały wprowadzone w Javie 8. Pozwalają one nam na wykonywanie działań na zbiorach takich jak sortowanie czy filtrowanie.
Ważnym aspektem jest jednak to, że operacje przeprowadzane na strumieniu nie wpływają bezpośrednio na naszą kolekcję, dlatego na przykład sortowanie strumienia nie wpływa na kolejność elementów w liście.

Rodzaje strumieni

Strumienie dzielimy na sekwencyjne lub równoległe. W przypadku pierwszym wszystkie operacje wykonywane są jedna po drugiej. W przypadku drugim natomiast, wykonywane są one równolegle w wielu wątkach co ma duże znaczenie w przypadku wielu rekordów.

Rodzaje operacji na strumieniach

Operacje dzielimy na pośrednie oraz kończące. W przypadku pierwszym jako wynik otrzymujemy strumień, dzięki czemu możemy na nim wykonać kolejną operację. Ilość operacji jest dowolna. Na przykład:

Operacje kończące zwracają wynik bądź są typu void. Ich wywołanie jest równoznaczne z zamknięciem strumienia. Na przykład funkcja count zwraca ilość elementów.

Przykład zastosowania

Dziś troszkę nietypowo, zaczniemy od przykładowego kodu, a zaraz odpowiemy sobie na pytanie co właściwie się tutaj wydarzyło.

W pierwszym przykładzie chcemy wyświetlić liczby które spełniają cztery warunki:
– liczba z przedziału od 0 do 1299
– liczba pierwsza
– kwadrat liczby mniejszy od 4096
– podwojona wartość większa od 16

I teraz pierwsza rzecz która przychodzi na myśl, przecież aby uzyskać ten sam efekt przy pomocy strumienia musieliśmy napisać więcej kodu niż w przypadku pętli for, prawda? Wybieramy tutaj jednak pomiędzy objętością kodu, gdzie różnica swoją drogą i tak nie jest duża, a czytelnością.

Jedna z podstawowych teorii programowania mówi, że kod czytany jest częściej niż pisany, dlatego powinniśmy postawić na czytelne nazewnictwo oraz organizację kodu. Jeżeli wrócilibyśmy do takiego kodu po jakimś czasie, łatwiej byłoby się nam odnaleźć w przypadku rozwiązania drugiego. I o ile w takich krótkich programach nie ma to większego znaczenia, to w przypadku wielkich projektów wygląda to zupełnie inaczej.

Dodatkowo jak już wcześniej wspomniałem strumienie nie wpływają bezpośrednio na kolekcję co też ma znaczenie w niektórych przypadkach, zaraz sami się przekonacie. Czas na przykład drugi.

Wprowadzamy do tablicy kilka obiektów typu String, chcielibyśmy wyświetlić tylko te które zaczynają się od znaku „a”, lub takie, które kończą się znakiem „2”.
Dodatkowo chcielibyśmy wyświetlić je wielkimi literami w sposób posortowany.

Tak jak wcześniej wspomniałem pomimo tego, że wykonaliśmy na tym zbiorze zarówno operacje sortowania jak i zmiany wartości nasza lista nie została naruszona. Dzięki temu możemy dalej przeprowadzać na niej inne operacje bez względu na to, jaki wynik zwrócił strumień.

Najczęściej wykorzystywane operacje na strumieniach

filter

Operacja ograniczająca, dzięki niej możemy konkretnie zdefiniować jakie warunki mają spełniać oczekiwane przez rekordy. Jest to operacja pośrednia. Jako parametr przyjmuje interfejs predykatu (jeżeli nie wiesz czym jest predykat to zapraszam do mojego wpisu o wyrażeniach lambda).

forEach

Operacja przyjmująca interfejs konsumenta, wykonanego dla każdego elementu który pozostał w strumieniu (spełnił jego warunki). Jest to operacja kończąca typu void.

sorted

Operacja pośrednia dzięki której możemy posortować strumień. Jako parametr przyjmuje Comparator. W przypadku jego braku posortuje elementy w sposób naturalny.

map

Dzięki tej operacji możemy zamienić dowolny element na inny typ. Jest to operacja pośrednia. W poniższym przykładzie konwertowane zostają liczby typu Integer na Stringi.

match

Operacja kończąca typu boolean, która jako parametr przyjmuje interfejs predykatu. Pozwala nam sprawdzić czy dany strumień spełnia warunek:
anyMatch – chociaż jeden
allMatch – wszystkie
noneMatch – żaden

Takim oto sposobem dotarliśmy do końca wpisu. Strumienie są bardzo intuicyjne i proste w użyciu, a bardzo mocno zwiększają przejrzystość kodu. Do tego dzięki przetwarzaniu równoległemu możemy zmniejszyć czas przetwarzania niektórych operacji. Zachęcam do przećwiczenia tematu samemu. Jak zawsze następny wpis w przyszłym tygodniu. Miłego wieczoru!

Your email address will not be published. Required fields are marked *

*