java - 基于每个日期 java 列表上特定记录的最大字段的 GroupBy 和流过滤器

标签 java filter java-stream collectors maxby

我有一个如下所示的列表

[
  {
    "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
  }
]

我想要实现的是过滤,例如在日期 2022-08-27 和日期 2022-08-26 分别我只返回一个记录具有最大currentSpeed,这样我的最终列表如下所示

[
  {
    "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
  }
]

下面是我的代码的样子以及我填充列表的方式

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")));

    }

下面是我试图用来过滤的内容,但我在下面的过滤器代码中得到了不是语句

        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));

有没有一种有效的方法可以用来过滤

最佳答案

如果您需要最大currentSpeed的 map 对于每个,那么您需要按分组并映射到具有当前速度最大值的 HashMap 。您可以使用LocalDateTime来自java.time用于解析日期的 API,以便更轻松地使用 map 值作为分组分类器。

基本上您想要的步骤是:

  • 流式传输您的列表
  • 使用日期作为键收集到 map
  • 映射到最大值为 currentSpeed 的 HashMap 使用BinaryOperator和一个 Comparator
  • 上述步骤将产生 Map<LocalDate, HashMap<String, Object>>
  • 最后从上面的 map 中获取值

代码:

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);

您还可以使用Collectors.groupingByCollectors.reducing 结合但是您需要解开减少步骤产生的可选内容

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);

关于java - 基于每个日期 java 列表上特定记录的最大字段的 GroupBy 和流过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73605690/

相关文章:

java - 三个maven项目A依赖B,B依赖C,如何让C在编译时对A不可见?

java - "Connection is not associated with a managed connection"更改MySQL的JDBC驱动程序后

java - 如何在使用列表在 map 中分组时过滤年龄

ios - 使用来自其他 View 的查询过滤 TableView

java - 使用并行流从 java 列表中获取 Pojo,而不使用任何类型的索引

java - 如何在 gridView 上添加 OnTouchListener?

python - pymunk 更新了形状过滤器的使用

java - Collectors.joining (",") 是线程安全的吗?

Java使用流中的重复元素创建多个列表

java - Eclipse导入jar包,启动Tomcat还是找不到class