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 aBinaryOperator
and aComparator
- 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);