Search code examples
javajava-8hashmapjava-stream

Hashmap - Grouping by Month


List of items which shows the date of the category and need to group them based on a dates and total amount of the each category. How should I do it?

My java code:

final Map<String, TemporalAdjuster> ADJUSTERS = new HashMap<>();
ADJUSTERS.put("day", TemporalAdjusters.ofDateAdjuster(d -> d)); // identity
ADJUSTERS.put("week", TemporalAdjusters.previousOrSame(DayOfWeek.of(1)));
ADJUSTERS.put("month", TemporalAdjusters.firstDayOfMonth());
ADJUSTERS.put("year", TemporalAdjusters.firstDayOfYear());

Map <LocalDate, List<Data>> TotalVal = ldata
        .stream()
        .sorted(Comparator
                .comparingInt(Data::getAmount)
                .reversed()
        )
        .collect(Collectors
                .groupingBy(item -> item.getDate().with(ADJUSTERS.get("month")))
                .collect(Collectors
                        .toMap(Data::getName, 
                                Data::getAmount, 
                                (sumAmt, amt) -> sumAmt + amt, 
                                LinkedHashMap::new)
                )
        );

My input as json:

Statement: [
  {
    "date": "12-09-19",
    "Category": "Bills",
    "Amount": "100"
  },
  {
    "date": "11-09-19",
    "Category": "Grocery",
    "Amount": "1010"
  },
  {
    "date": "21-08-19",
    "Category": "Other Household Bills",
    "Amount": "1320"
  },
  {
    "date": "11-08-19",
    "Category": "Service",
    ,
    "Amount": "2100"
  },
  {
    "date": "11-09-19",
    "Category": "Food & Dining Out",
    "Amount": "1010"
  },
  {
    "date": "21-08-19",
    "Category": "Service",
    "Amount": "100"
  },
  {
    "date": "18-09-19",
    "Category": "Bills",
    "Amount": "100"
  }
]

My expected output:

Sep-19 Grocery:1010, Food & Dining Out:1010, Bills:200 Aug-19 Service:2200, Other Household Bills:1320


Solution

  • First group by month-year, then group by category.

    public class Main {
    
      public static void main(String[] args) {
        List<Data> data = List.of(
            new Data(LocalDate.of(2019, 9, 12), "Bills", 100),
            new Data(LocalDate.of(2019, 9, 11), "Grocery", 1010),
            new Data(LocalDate.of(2019, 8, 21), "Other Household Bills", 1320),
            new Data(LocalDate.of(2019, 8, 11), "Service", 2100),
            new Data(LocalDate.of(2019, 8, 21), "Food & Dining Out", 1010),
            new Data(LocalDate.of(2019, 9, 18), "Bills", 100)
        );
    
        var result = data.stream()
            .collect(Collectors.groupingBy(
                data1 -> data1.getDate().getMonth()+"-"+ data1.getDate().getYear(),
                Collectors.groupingBy(Data::getCategory, Collectors.summingInt(Data::getAmount))
            ));
    
        result.forEach((localDate, stringIntegerMap) -> {
          System.out.print(localDate +" ");
          stringIntegerMap.forEach((s, integer) -> System.out.print(s + " :" + integer+" "));
          System.out.println();
    
        });
      }
    
    }
    
    class Data {
    
      private LocalDate date;
      private String category;
      private int amount;
    
      public Data(LocalDate date, String category, int amount) {
        this.date = date;
        this.category = category;
        this.amount = amount;
      }
      //getters & setters
    }