1

I have created a HashMap using json response which I want to use its data group by month.

My json

[
   {
      "type":"CLAIMS PAID",
      "category":"01. Less than 0",
      "month":11,
      "year":2020,
      "count":173
   },
   {
      "type":"CLAIMS PAID",
      "category":"02. 1-5",
      "month":11,
      "year":2020,
      "count":445
   },
   {
      "type":"CLAIMS PAID",
      "category":"03. 6-10",
      "month":11,
      "year":2020,
      "count":362
   },
   {
      "type":"CLAIMS PAID",
      "category":"04. 11-15",
      "month":11,
      "year":2020,
      "count":241
   },
   {
      "type":"CLAIMS PAID",
      "category":"05. 16-20",
      "month":11,
      "year":2020,
      "count":130
   },
   {
      "type":"CLAIMS PAID",
      "category":"06. 21-25",
      "month":11,
      "year":2020,
      "count":115
   },
   {
      "type":"CLAIMS PAID",
      "category":"07. 26-30",
      "month":11,
      "year":2020,
      "count":66
   },
   {
      "type":"CLAIMS PAID",
      "category":"08. 31-35",
      "month":11,
      "year":2020,
      "count":32
   },
   {
      "type":"CLAIMS PAID",
      "category":"09. More than 35",
      "month":11,
      "year":2020,
      "count":251
   },
   {
      "type":"CLAIMS PAID",
      "category":"01. Less than 0",
      "month":12,
      "year":2020,
      "count":257
   },
   {
      "type":"CLAIMS PAID",
      "category":"02. 1-5",
      "month":12,
      "year":2020,
      "count":726
   },
   {
      "type":"CLAIMS PAID",
      "category":"03. 6-10",
      "month":12,
      "year":2020,
      "count":722
   },
   {
      "type":"CLAIMS PAID",
      "category":"04. 11-15",
      "month":12,
      "year":2020,
      "count":378
   },
   {
      "type":"CLAIMS PAID",
      "category":"05. 16-20",
      "month":12,
      "year":2020,
      "count":207
   },
   {
      "type":"CLAIMS PAID",
      "category":"06. 21-25",
      "month":12,
      "year":2020,
      "count":151
   },
   {
      "type":"CLAIMS PAID",
      "category":"07. 26-30",
      "month":12,
      "year":2020,
      "count":94
   },
   {
      "type":"CLAIMS PAID",
      "category":"08. 31-35",
      "month":12,
      "year":2020,
      "count":56
   },
   {
      "type":"CLAIMS PAID",
      "category":"09. More than 35",
      "month":12,
      "year":2020,
      "count":351
   },
   {
      "type":"CLAIMS PAID",
      "category":"01. Less than 0",
      "month":1,
      "year":2021,
      "count":254
   },
   {
      "type":"CLAIMS PAID",
      "category":"02. 1-5",
      "month":1,
      "year":2021,
      "count":693
   },
   {
      "type":"CLAIMS PAID",
      "category":"03. 6-10",
      "month":1,
      "year":2021,
      "count":538
   },
   {
      "type":"CLAIMS PAID",
      "category":"04. 11-15",
      "month":1,
      "year":2021,
      "count":287
   },
   {
      "type":"CLAIMS PAID",
      "category":"05. 16-20",
      "month":1,
      "year":2021,
      "count":194
   },
   {
      "type":"CLAIMS PAID",
      "category":"06. 21-25",
      "month":1,
      "year":2021,
      "count":144
   },
   {
      "type":"CLAIMS PAID",
      "category":"07. 26-30",
      "month":1,
      "year":2021,
      "count":110
   },
   {
      "type":"CLAIMS PAID",
      "category":"08. 31-35",
      "month":1,
      "year":2021,
      "count":73
   },
   {
      "type":"CLAIMS PAID",
      "category":"09. More than 35",
      "month":1,
      "year":2021,
      "count":372
   },
   {
      "type":"CLAIMS PAID",
      "category":"01. Less than 0",
      "month":2,
      "year":2021,
      "count":225
   },
   {
      "type":"CLAIMS PAID",
      "category":"02. 1-5",
      "month":2,
      "year":2021,
      "count":960
   },
   {
      "type":"CLAIMS PAID",
      "category":"03. 6-10",
      "month":2,
      "year":2021,
      "count":733
   },
   {
      "type":"CLAIMS PAID",
      "category":"04. 11-15",
      "month":2,
      "year":2021,
      "count":360
   },
   {
      "type":"CLAIMS PAID",
      "category":"05. 16-20",
      "month":2,
      "year":2021,
      "count":200
   },
   {
      "type":"CLAIMS PAID",
      "category":"06. 21-25",
      "month":2,
      "year":2021,
      "count":145
   },
   {
      "type":"CLAIMS PAID",
      "category":"07. 26-30",
      "month":2,
      "year":2021,
      "count":107
   },
   {
      "type":"CLAIMS PAID",
      "category":"08. 31-35",
      "month":2,
      "year":2021,
      "count":51
   },
   {
      "type":"CLAIMS PAID",
      "category":"09. More than 35",
      "month":2,
      "year":2021,
      "count":271
   }
]

Object class

public class Item{

    private String type;
    private String category;
    private int month;
    private int year;
    private String monthName;
    private String count;

}


                JSONArray resArray = new JSONArray(jsonresponse);
                for (int i = 0; i < resArray.length(); i++) {

                    JSONObject jo = resArray.getJSONObject(i);
                    Item ariData = new Item();
                    ariData.setType(jo.getString("type"));
                    ariData.setCategory(jo.getString("category"));
                    ariData.setYear(jo.getInt("year"));
                    ariData.setMonth(jo.getInt("month"));
                    ariData.setMonthName(getMonthFullName(jo.getInt("month")));
                    ariData.setCount(jo.getString("count"));
                    ariList.add(ariData);

                }

I want to display same month's data in a RecyclerView so I have grouped by this json its Month for display in the RecyclerView. So I put it into a HashMap using..

Map<Integer, List<Item>> objectsPer = ariList.stream()
                                .collect(Collectors.groupingBy(Item::getMonth));

Problem is, If there is two years' data for example 2020-12 and 2021-01 then 2020-12 month's data display after 2021-01 data. I know this is happening because of the group by using month. I want to sort this HashMap using year also.

Edit

public class Item{

private String type;
private String category;
private String count;
private int total;
private YearMonth yearMonth;

}

  JSONArray resArray = new JSONArray(response);
                        for (int i = 0; i < resArray.length(); i++) {

                            JSONObject jo = resArray.getJSONObject(i);
                            Item ariData = new Item();
                            ariData.setType(jo.getString("type"));
                            ariData.setCategory(jo.getString("category"));
                            ariData.setCount(jo.getString("count"));
                            YearMonth yMonth = YearMonth.of(jo.getInt("year"), jo.getInt("month"));
                            ariData.setYearMonth(yMonth);
                            ariList.add(ariData);

                        }

                        Map<YearMonth, List<Item>> objectsPer = ariList.stream()
                                .collect(Collectors.groupingBy(Item::getYearMonth));

Here I put date range in 2021-03 to 2021-06

see the debug I get for this date range after group by using year month

enter image description here

Here I put date range in 2020-11 to 2021-06

enter image description here

9
  • 1
    If you group by month only, 1 will always be before 12... You have to consider the year, too. Hint: You can use a java.time.YearMonth. Commented Jun 21, 2021 at 7:24
  • can I do multiple grouping like Collectors.groupingBy(Item::getYear, Item::getMonth) ? I tried by this is not working Commented Jun 21, 2021 at 7:28
  • 1
    That's why I involved the YearMonth, make an Item have a YearMonth instead of a year, a month and a month name. This class provides each of those and you can group by that attribute and the sorting will be as desired. You can instantiate it by YearMonth.of(int year, int month) and get the month name by yearMonth.getMonth().getDisplayName(TextStyle.FULL, Locale.ENGLISH);. Commented Jun 21, 2021 at 7:31
  • 1
    Then try this line: NavigableMap<YearMonth, Set<Item>> objectsPer = ariList.stream().collect(Collectors.groupingBy(Item::getYearMonth, TreeMap::new, Collectors.toSet())); Commented Jun 21, 2021 at 10:39
  • 1
    @deHaar thankx. I tried Map<YearMonth, List<Item>> unsortMap = ariList.stream().collect(Collectors.groupingBy(Item::getYearMonth)); Map<YearMonth, List<Item>> sortMap = new TreeMap<>(unsortMap); It also worked, your solution also worked Commented Jun 21, 2021 at 11:15

1 Answer 1

1

YearMonth

As commented by deHaar, you should be using the java.time.YearMonth class rather than your separate int fields for year and for month. And no need for storing month name as that can be determined dynamically by calling YearMonth#getMonth and Month#getDisplayName.

Redefine your class, with less fields: String type, String category, YearMonth yearMonth, int count.

(Shouldn’t count be an integer number rather than String?)

By the way, in Java 16+, we can define a class more briefly as a record if its main purpose is to communicate data transparently and immutably. Simply declare the type and name of each member field. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString. You can even declare a record locally.

public record Item ( String type, String category, YearMonth yearMonth,  int count ) {}

You could just as well define a conventional class in the context of this Answer. A record is simply more convenient.

By the way, type and category should probably be defined each in their own enum rather than as String. But that’s a whole other matter.

NavigableMap, NavigableSet

Collect your Item objects in a map. Use a navigable map and navigable set to keep sorted by YearMonth.

Perhaps use TreeMap and TreeSet as your choice of implementations. When constructing the TreeSet objects, pass a Comparator to organize the sorting.

NavigableMap< YearMonth , NavigableSet< Item > > = …
Sign up to request clarification or add additional context in comments.

2 Comments

count is int value. I am not familiar with NavigableMap. I tried and I am getting error when I use NavigableMap<YearMonth, NavigableSet<Item >> objectsPer = ariList.stream() .collect(Collectors.groupingBy(Item ::getYearMonth));
@D.madushanka Past my bedtime, but I may be able to write more code on another day. All this has been covered already on Stack Overflow if you search to learn more.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.