2017-06-05 34 views
5

Mam java.util.stream.Stream zawierający pary wartość klucza jak:Java 8: Wykonywanie operacji na zmniejszenie Stream

<1,3> <1,5> <3,1> <4,2> <4,7> <4,8> 

teraz chciałbym, aby połączyć wszystkie wpisy, które posiadają takie same klucz:

<1,[3,5]> <3,[1]> <4,[2,7,8]> 

Dane są już posortowane, więc należy połączyć tylko kolejne zbiory danych.

Teraz szukam sposobu na przekształcenie zawartości strumienia, jak powyżej, bez ładowania wszystkich zbiorów danych do pamięci.

Wolałbym otrzymać java.util.stream.Stream jako wynik dla innego typu obiektu zawierającego listę wartości zamiast jednej wartości.

Moje jedyne podejście to niestandardowy iterator, który wykonuje scalenie, ale wydaje się dość brzydki, aby przekonwertować go na iterator i wrócić do strumienia.

Jakie jest dla niego najlepsze podejście?

+6

Znalazłeś prawdopodobnie najlepszą dostępną opcję. Strumień nie jest przeznaczony do tego rodzaju operacji, jakie chcesz. –

+0

Myślę, że operacja '.groupBy()' może działać w zależności od tego, co dokładnie znajduje się w strumieniu. @LouisWasserman może jednak lepiej zrozumiał Twoje wymagania. – KevinO

+0

@KevinO, PO wyraźnie stwierdził, że nie chcieli w rezultacie strumienia, i aby uniknąć ładowania danych do pamięci. 'groupingBy' nie pozwoli ci tego zrobić. –

Odpowiedz

4

Oto rozwiązanie: SteamEx.

int[][] datasets = { { 1, 3 }, { 1, 5 }, { 3, 1 }, { 4, 2 }, { 4, 7 }, { 4, 8 } }; 

StreamEx.of(datasets) // 
     .collapse((a, b) -> a[0] == b[0], groupingBy(a -> a[0], mapping(a -> a[1], toList()))) // 
     .forEach(System.out::println); 

można zastąpić int[] z obiektem dataset. Możemy dodać peek, aby sprawdzić, czy jest to leniwe ładowanie/obliczanie:

StreamEx.of(datasets) // 
     .peek(System.out::println) // 
     .collapse((a, b) -> a[0] == b[0], groupingBy(a -> a[0], mapping(a -> a[1], toList()))) // 
     .limit(1) // 
     .forEach(System.out::println);