2015-05-23 25 views
5

Chcę zgrupować listę obiektów zawierającą atrybut time w odstępach 5-minutowych, najlepiej przy użyciu strumieni i kolektorów.Jak grupować obiekty na liście na inne listy według atrybutów wykorzystujących strumienie i Java 8?

Jedynym możliwym rozwiązaniem, które znalazłem na StackOverflow, jest obliczenie, ile interwałów (podlistek) potrzebuję, dodanie każdego obiektu do każdej z tych list i odfiltrowanie tych, które nie pasują do odpowiednich ram czasowych, co nie jest dokładnie takie fajne rozwiązanie.

(Można znaleźć wątek tutaj: How to group elements of a List by elements of another in Java 8)

myślałem o czymś podobnym do tego:

List<MyObject> list = new ArrayList<MyObject>(); 
....... 
List<List<MyObject>> grouped = list.stream().collect(Collectors.groupingBy(obj -> obj.getTime()/intervalLength)); 

To oczywiście doenst pracy.

Mam nadzieję, że dzięki zastosowaniu Java 8 &, jego funkcje będą coraz częściej używane, możemy znaleźć rozwiązanie dla tego problemu.

Pozdrawiam, Claas M.

EDIT: W końcu użyłem rozwiązanie @Harsh Poddar i konwertowane Mapa na listę list używając

for(Map.Entry<Integer, List<MyObject>> entry:map.entrySet()) 
    list.add(entry.getValue()); 

Uwaga: Lista musiał być posortowane później.

Odpowiedz

4

ten działa całkowicie w porządku:

Map<Long,<List<MyObject>> grouped = ticks.stream().collect(Collectors.groupingBy(obj -> obj.getTime()/intervalLength)); 

Ta metoda daje mapę, na której można następnie zadzwonić .values ​​(), aby uzyskać listę list. Pierwszy element będzie zawierał elementy z obj.getTime() od 0 do intervalLength pod warunkiem, że były takie elementy. Drugi będzie zawierać od intervalLength do intervalLength * 2 i tak dalej

+0

To zadziałało, dziękuję! –

4

Użyj funkcji mapowania czasu do wiadra:

// assume time is in seconds 
int bucketNumber(int baseTime, int thisTime) { 
    return (thisTime - baseTime)/300; 
} 

Następnie zebrać liczby wieloczynnościowy:

ticks.stream().collect(groupingBy(e -> bucketNumber(baseTime, e.getTime())); 

teraz ty mieć Map<Integer, List<Tick>>, gdzie klucz jest indeksem pięciominutowego zasobnika zaczynającego się od baseTime, oraz listą znaczników w tym zasobniku. Jeśli chcesz tylko histogramu, użyj kolektora w dół:

ticks.stream().collect(groupingBy(e -> bucketNumber(baseTime, e.getTime()), 
            counting()); 
+1

@HarshPoddar Do ciebie. Próbowałem zilustrować, jak rozwiązać problem, ponieważ wydawało się, że OP ma kłopoty. –

+0

Dzięki za odpowiedź! –

Powiązane problemy