Historia pytania:
Stream API został dodany w Java 8, aby ułatwić programowanie funkcjonalne i równoległe przetwarzanie kolekcji. Oferuje wygodny sposób opisywania łańcuchów operacji na danych za pomocą wyrażeń lambda.
Problem:
Bez Stream API trzeba było pisać rozbudowany, imperatywny kod do filtrowania, sortowania i agregowania kolekcji. Potencjał do błędów, złożoność utrzymania, nieefektywność przy próbie dodania równoległości ręcznie.
Rozwiązanie:
Stream API pozwala zbudować pipeline z operacji pośrednich (intermediate) i końcowych (terminal). Strumienie są leniwe, działają z danymi sekwencyjnie lub równolegle, kod staje się bardziej zwarty i wyrazisty.
Przykład przetwarzania kolekcji:
List<String> names = Arrays.asList("Anna", "Iwan", "Piotr", "Ewa"); names.stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .sorted() .forEach(System.out::println);
Kluczowe cechy:
parallelStream()), ale należy uwzględnić bezpieczeństwo wątków kolekcji i funkcjiCzy można ponownie użyć tego samego Strumienia po jego zamknięciu?
Nie, próba ponownego użycia zamkniętego Strumienia zgłasza IllegalStateException. Strumień jest jednorazowy.
Czy zmiana pierwotnej kolekcji po utworzeniu Strumienia ma wpływ?
Tak, jeśli kolekcja zostanie zmieniona po utworzeniu Strumienia, ale przed operacją końcową, mogą wystąpić ConcurrentModificationException.
Czy można używać zewnętrznych zmiennych w stream-operatorach?
Nie zaleca się, ponieważ w równoległym strumieniu może to prowadzić do nieoczekiwanych błędów. Lepiej unikać mutowalnych efektów ubocznych w pipeline'ie Strumienia.
.parallelStream() do kolekcji, które nie są bezpieczne dla wątkówProgramista wywołuje za pomocą Strumienia pewną metodę, która zmienia zewnętrzną listę - działa to przy sekwencyjnym wykonywaniu, ale przy równoległym daje zaburzenie struktury danych.
Zalety:
Wady:
Cały pipeline jest budowany czysto: operacje nie mają efektów ubocznych, używane są tylko niemutowalne kolekcje, finalny wynik jest zbierany za pomocą collector.
Zalety:
Wady: