Wpis z mikrobloga

Czołem Mirki,
Mam taki problem do rozwiązania w Javie:

Mam mapę obiektów LocalDateTime na obiekty Long.

LDT1 -> 2
LDT2 -> 4
LDT3 -> 7
LDT4 -> 1
LDT5 -> 4
...
LDTx -> y

Chciałbym - wykorzustując streamy i dobrodziejstwa Javy 8 - utworzyć nową mapę, w której pod kluczami (LocalDateTime) będą trzymane sumy wszystkich liczb, dla których klucz jest mniejszy lub równy od aktualnie przetwarzanego.

Założmy, że LDT1 < LDT2 < LDT3 < ... < LDTx (mapa nie jest sortowana, ale to dla streamów obojętne).
Chciałbym, żeby nowa mapa zawierała:

LDT1 -> 2
LDT2 -> 2 +4 = 6
LDT3 -> 2 + 4 + 7 = 13
LDT4 -> 2 + 4 + 7 + 1 = 14
LDT5 -> 2 + 4 + 7 + 1 + 4 = 18
...
LDTx -> suma wszystkich wartości

Proszę o pomoc.
Próbowlem bezskutecznie z Collectors.groupingBy, Collectors.counting i nie mam generalnei pomysłu jak to ugryźć.

Map mapa;
Map wynik = mapa.entrySet().stream()...

#programowanie #java
  • 2
@macentos: Streamy mają to do siebie, że każdy element jest traktowany indywidualnie, więc collectora, który zrobi taką robotę nie ma. Zatem jeśli chcesz czysto streamowe rozwiązanie, to nie obejdzie się bez dwóch streamów, na przykład tak (dla przejrzystości statyczne importy i brak przypisania wyniku do zmiennej):

map.keySet()
   .stream()
   .collect(toMap(identity(), k -> map.entrySet()
                                      .stream()
                                      .filter(e -> !e.getKey().isAfter(k))
                                      .mapToLong(Map.Entry::getValue)
                                      .sum()));

albo tak jak radziła koleżanka wyżej, jeśli map jest TreeMap, to:

map.keySet()
   .stream()
   .collect(toMap(identity(), k -> map.headMap(k, true)
                                      .values()
                                      .stream()
                                      .mapToLong(l -> l)