Odpowiedź brzmi, jak zawsze, „to zależy”. Zależy to od tego, jak duża będzie zwracana kolekcja. Zależy to od tego, czy wynik zmienia się w czasie i jak ważna jest spójność zwracanego wyniku. Zależy to w dużej mierze od tego, jak użytkownik prawdopodobnie użyje odpowiedzi.
Po pierwsze, pamiętaj, że zawsze możesz pobrać kolekcję ze strumienia i odwrotnie:
// If API returns Collection, convert with stream()
getFoo().stream()...
// If API returns Stream, use collect()
Collection<T> c = getFooStream().collect(toList());
Pytanie brzmi, co jest bardziej przydatne dla dzwoniących.
Jeśli Twój wynik może być nieskończony, jest tylko jeden wybór: Stream.
Jeśli twój wynik może być bardzo duży, prawdopodobnie wolisz Stream, ponieważ może nie mieć żadnej wartości w materializacji tego wszystkiego naraz, a zrobienie tego może spowodować znaczną presję na stertę.
Jeśli wszystko, co ma zamiar wywołać, to iteracja (wyszukiwanie, filtrowanie, agregowanie), powinieneś preferować Stream, ponieważ Stream ma już te wbudowane i nie ma potrzeby materializacji kolekcji (zwłaszcza jeśli użytkownik może nie przetwarzać cały wynik). Jest to bardzo częsty przypadek.
Nawet jeśli wiesz, że użytkownik dokona iteracji wiele razy lub w inny sposób zachowa go w pobliżu, nadal możesz chcieć zamiast tego zwrócić strumień, z prostego powodu, że niezależnie od kolekcji, w której zdecydujesz się go umieścić (np. ArrayList), może nie być formularz, który chcą, a następnie dzwoniący i tak musi go skopiować. jeśli zwrócisz strumień, mogą to zrobić collect(toCollection(factory))
i uzyskać dokładnie taką formę, jaką chcą.
Powyższe przypadki „preferuj Stream” wynikają głównie z faktu, że Stream jest bardziej elastyczny; możesz później powiązać się z tym, jak go używasz, bez ponoszenia kosztów i ograniczeń związanych z materializacją go w kolekcji.
Jedynym przypadkiem, w którym musisz zwrócić kolekcję, jest sytuacja, gdy istnieją wysokie wymagania dotyczące spójności i musisz stworzyć spójną migawkę poruszającego się celu. Następnie będziesz chciał umieścić elementy w kolekcji, która się nie zmieni.
Powiedziałbym więc, że w większości przypadków Stream jest właściwą odpowiedzią - jest bardziej elastyczny, nie narzuca zwykle niepotrzebnych kosztów materializacji iw razie potrzeby można go łatwo przekształcić w wybraną przez Ciebie Kolekcję. Ale czasami może być konieczne zwrócenie kolekcji (powiedzmy, ze względu na rygorystyczne wymagania dotyczące spójności) lub możesz chcieć zwrócić kolekcję, ponieważ wiesz, w jaki sposób użytkownik będzie z niej korzystać, i wiesz, że jest to dla niego najwygodniejsze.
players.stream()
to taka metoda, która zwraca strumień do wywołującego. Prawdziwe pytanie brzmi: czy naprawdę chcesz ograniczyć wywołującego do pojedynczego przejścia, a także odmówić mu dostępu do Twojej kolekcji przezCollection
API? Może dzwoniący po prostu chceaddAll
to do innej kolekcji?