Skip to content
Advertisement

GroupBy and Stream Filter based on max field for particular record on each date java list

I am having a list that looks like below

[
  {
    "busId": "4-3323309834",
    "dataDateTime": "2022-08-27 05:22:46",
    "busName": "27Tr Solaris Single Deck",
    "speedLimit": 80,
    "id": 1,
    "currentSpeed": 67,
    "passengersNo": 80
  },
  {
    "busId": "4-3323309834",
    "dataDateTime": "2022-08-27 07:12:10",
    "busName": "27Tr Solaris Single Deck",
    "speedLimit": 80,
    "id": 2,
    "currentSpeed": 56,
    "passengersNo": 11
  },
  {
    "busId": "4-3323309834",
    "dataDateTime": "2022-08-26 03:12:10",
    "busName": "27Tr Solaris Single Deck",
    "speedLimit": 80,
    "id": 3,
    "currentSpeed": 31,
    "passengersNo": 15
  },
  {
    "busId": "4-3323309834",
    "dataDateTime": "2022-08-26 03:12:10",
    "busName": "27Tr Solaris Single Deck",
    "speedLimit": 80,
    "id": 3,
    "currentSpeed": 78,
    "passengersNo": 15
  },
  {
    "busId": "4-3323309834",
    "dataDateTime": "2022-08-26 04:34:10",
    "busName": "27Tr Solaris Single Deck",
    "speedLimit": 80,
    "id": 7,
    "currentSpeed": 49,
    "passengersNo": 57
  }
]

What i would like to achieve is to filter like for example on date 2022-08-27 and also on date 2022-08-26 respectively i only return one record which is having the maximum currentSpeed such that my final list looks like below

[
  {
    "busId": "4-3323309834",
    "dataDateTime": "2022-08-27 05:22:46",
    "busName": "27Tr Solaris Single Deck",
    "speedLimit": 80,
    "id": 1,
    "currentSpeed": 67,
    "passengersNo": 80
  },
  {
    "busId": "4-3323309834",
    "dataDateTime": "2022-08-26 03:12:10",
    "busName": "27Tr Solaris Single Deck",
    "speedLimit": 80,
    "id": 3,
    "currentSpeed": 78,
    "passengersNo": 15
  }
]

Below is how my code looks like and the way i am populating my list

public static void main(String[] args) {

        List<HashMap<String, Object>> myList = new ArrayList<>();

        myList.add(new HashMap<>(Map.of("id", 1,
                "busId","4-3323309834",
                "busName","27Tr Solaris Single Deck",
                "currentSpeed",67,
                "passengersNo",80,
                "speedLimit",80,
                "dataDateTime","2022-08-27 05:22:46")));

        myList.add(new HashMap<>(Map.of("id",2,
                "busId","4-3323309834",
                "busName","27Tr Solaris Single Deck",
                "currentSpeed",56,
                "passengersNo",11,
                "speedLimit",80,
                "dataDateTime","2022-08-27 07:12:10")));

        myList.add(new HashMap<>(Map.of(
                "id",3,
                "busId","4-3323309834",
                "busName","27Tr Solaris Single Deck",
                "currentSpeed",31,
                "passengersNo",15,
                "speedLimit",80,
                "dataDateTime","2022-08-26 03:12:10")));

        myList.add(new HashMap<>(Map.of(
                "id",3,
                "busId","4-3323309834",
                "busName","27Tr Solaris Single Deck",
                "currentSpeed",78,
                "passengersNo",15,
                "speedLimit",80,
                "dataDateTime","2022-08-26 03:12:10")));

        myList.add(new HashMap<>(Map.of(
                "id",7,
                "busId","4-3323309834",
                "busName","27Tr Solaris Single Deck",
                "currentSpeed",49,
                "passengersNo",57,
                "speedLimit",80,
                "dataDateTime","2022-08-26 04:34:10")));

    }

Below is what i am trying to use to filter but i a getting Not a statement in below filter code

        List<HashMap<String, Object>> myList2 = myList.stream()
                .collect(Collectors.groupingBy(hashmap ->
                                List.of(hashmap.get("busId"),
                                        hashmap.get("currentSpeed"),
                        Collectors.maxBy(Comparator.comparing(HashMap::get("dataDateTime")))));




        System.out.println(Config.ANSI_CYAN + "MyListToJsonPrint: " +
                new GsonBuilder().setPrettyPrinting().create().toJson(myList2));

Is there an efficient way that i can use to filter

Advertisement

Answer

If you need the map having the max currentSpeed for each day, then you need to group by day and map to the hashmap having the max value of current speed. You can use LocalDateTime from the java.time API to parse your dates so that it is easier to use your map values as a classifier for grouping.

Basically the steps you want are:

  • Stream over your list
  • collect to map using the date as key
  • map to the hashmap having the max value of currentSpeed using a BinaryOperator and a Comparator
  • the above steps will result in a Map<LocalDate, HashMap<String, Object>>
  • and finally get the values from the above map

Code:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

List<HashMap<String, Object>> result = new ArrayList<>(
        myList.stream()
              .collect(Collectors.toMap(map -> LocalDateTime.parse((String) map.get("dataDateTime"), dtf).toLocalDate(),
                                        Function.identity(),
                                        BinaryOperator.maxBy(Comparator.comparingInt(map -> (int)map.get("currentSpeed")))))
              .values());

result.forEach(System.out::println);

You could also use Collectors.groupingBy in combination with Collectors.reducing but you need then to unwrap the optional resulting from the reducing step

List<HashMap<String, Object>> result2 = new ArrayList<>(
myList.stream()
       .collect(Collectors.groupingBy(map -> LocalDateTime.parse((String) map.get("dataDateTime"), dtf).toLocalDate(),
                                      Collectors.collectingAndThen(
                                              Collectors.reducing(BinaryOperator.maxBy(Comparator.comparingInt(map -> (int)map.get("currentSpeed")))),
                                              Optional::get))).values());

result2.forEach(System.out::println);
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement