Zacznę od ogólnego stwierdzenia, że specyfikacja języka Java nakłada pewne ograniczenia dotyczące implementacji strumieni. Tak naprawdę nie jest zbyt ważne, aby zapytać o wydajność strumieni Java: będzie się znacznie różnić między implementacjami.
Należy również pamiętać, że interfejs to Stream
. Możesz utworzyć własną klasę, która implementuje Stream
, aby uzyskać dowolną wydajność lub specjalne zachowanie na poziomie sorted
. Tak naprawdę pytanie o wydajność Stream
nie ma sensu nawet w kontekście jednej implementacji. Implementacja OpenJDK ma wiele klas, które implementują interfejs Stream
.
Powiedziawszy to, jeśli przyjrzymy się implementacji OpenJDK, sortowanie strumieni kończy się w klasie SortedOps
(patrz źródło here), przekonasz się, że metody sortowania kończą się powracaniem rozszerzeń operacji stanowych. Na przykład:
private static final class OfInt extends IntPipeline.StatefulOp<Integer>
Te metody sprawdzają, czy wcześniejszy kanał jest już posortowany, w takim przypadku przekazują go do dalszego przetwarzania. Mają także specjalne wyjątki dla strumieni o rozmiarach (tj. W górę), które wstępnie alokują tablice, które ostatecznie sortują, co poprawi efektywność (ponad SpinedBuffer
, której używają dla strumieni o nieznanym rozmiarze). Ale zawsze, gdy poprzedni element nie jest jeszcze posortowany, akceptują wszystkie elementy, a następnie sortują je, a następnie wysyłają do metody późniejszej instancji.
Wniosek stąd jest taki, że implementacja OpenJDK sorted
zbiera wszystkie elementy, a następnie sortuje, a następnie przesyła dalej. W niektórych przypadkach będzie to marnowanie zasobów, gdy dalszy użytkownik odrzuci niektóre elementy. Możesz zaimplementować własną wyspecjalizowaną operację sortowania, która jest bardziej wydajna niż w przypadku specjalnych przypadków.Prawdopodobnie najprostszym sposobem jest zaimplementowanie Collector
, który przechowuje listę n największych lub najmniejszych elementów w strumieniu. Twoja praca może wtedy wyglądać następująco:
.collect(new CollectNthLargest(4)).stream()
Aby wymienić
.sorted().limit(4)
Cały strumień jest posortowany. –
To zależy od charakterystyki tego strumienia; jeśli jego bazowy "Spliterator" zgłasza, że strumień jest "SORTOWANY", to "sort()" jest operacją zerową; w przeciwnym razie, jak już wspomniano, cały strumień jest sortowany, co oznacza, że wszystkie elementy utworzone przez strumień muszą zostać przeslane przed rozpoczęciem operacji sortowania - i to jest logiczne tylko – fge
@fge ... ale ... myślę o tym ... istnieją algorytmy, które otrzymają k najmniejszych elementów z listy nieposortowanej 'N' w' O (N) '. http://stackoverflow.com/questions/5380568/algorithm-to-find-k-smallest-numbers-in-array-of-n-items. Powinno być możliwe zaimplementowanie algorytmu dla strumieni w języku Java 8, ale nie w taki sposób, w jaki program OP próbuje to zrobić. –