Patrick
Patrick

Reputation: 12744

How to sort Map<YearMonth, List<LocalDate>> with java 8 lambda and streams

I have a list of sorted dates like this:

2016-07-07
2016-07-08
2016-07-09
2016-07-10
2016-07-11
2016-07-12
2016-07-13
...
2016-07-31
2016-08-01
2016-08-02
2016-08-03
...
2017-01-01
2017-01-02
2017-01-03
...

From this list I generate a Map<YearMonth, List<LocalDate>> with stream:

Map<YearMonth, List<LocalDate>> d = dates.stream().collect(Collectors.toList())
      .stream().collect(Collectors.groupingBy(date -> YearMonth.from(date)));

The output of that map looks like this:

{2016-12=[2016-12-01, 2016-12-02,...2016-12-31], 2016-11=[2016-11-01, 2016-11-02,...]}

But my needed output should look be like this:

I tried many options to get my expected result but I just get the correct sorting for the key or the value and not for both:

Map<YearMonth, List<LocalDate>> m = stream().collect(Collectors.toList())
      .stream().sorted((e1,e2) -> e2.compareTo(e1))
      .collect(Collectors.groupingBy(date -> YearMonth.from(date)));

Result:

{2016-07=[2016-07-31, 2016-07-30, ...], 2016-08=[2016-08-31, 2016-08-30, ...]}

How can I sort both by key and value?

Upvotes: 3

Views: 4294

Answers (4)

k5_
k5_

Reputation: 5558

Use a TreeMap as collector so the output is sorted by key.

Something like this:

 dates.stream()
      .sorted()
      .collect(
         Collectors.groupingBy(YearMonth::from, TreeMap::new, Collectors.toList())
      );

Upvotes: 4

Ashish Sharma
Ashish Sharma

Reputation: 41

You can sort them in the following way:-

Map<YearMonth, List<LocalDate>> map = dates.stream()
        .collect(Collectors.toList())
        .stream()
        .sorted((e1,e2) -> e1.compareTo(e2))
        .collect(Collectors.groupingBy(date -> YearMonth.from(date), TreeMap::new, Collectors.toList()));

Upvotes: 0

T. Neidhart
T. Neidhart

Reputation: 6200

You can use specific Collectors that return a sorted Collection. In your case I would use a TreeMap to sort the resulting Map by its keys, and explicitly sort the resulting value collections like that:

Map<YearMonth, List<LocalDate>> m = dates.stream()
   .collect(Collectors.groupingBy(
              date -> YearMonth.from(date),
              TreeMap::new,
              Collectors.collectingAndThen(
                Collectors.toList(),
                (list) -> { Collections.sort(list); return list; })));

Upvotes: 1

Andrew Kolpakov
Andrew Kolpakov

Reputation: 439

Collectors.groupingBy(date -> YearMonth.from(date)) internally stores result in HashMap and key sorting is lost.

This implementation will preserve keys order:

  Map<YearMonth, List<LocalDate>> d = dates
        .stream()
        .sorted((e1,e2) -> e2.compareTo(e1))
        .collect(Collectors
                .groupingBy(YearMonth::from,
                        LinkedHashMap::new,
                        Collectors.toList()));

Upvotes: 3

Related Questions