-
取出分组后每组最大值对象的ID
如果只需要获取这些对象的ID(或其他特定字段),而不是整个对象,可以采用以下方法:
方法1:先获取对象再提取ID
List<String> customerIds = orders.stream() .collect(Collectors.groupingBy( Order::getCustomerId, Collectors.maxBy(Comparator.comparing(Order::getOrderDate)) )) .values().stream() .filter(Optional::isPresent) .map(Optional::get) .map(Order::getCustomerId) // 提取ID字段 .collect(Collectors.toList());
方法2:直接在收集时提取ID(更高效)
List<String> customerIds = orders.stream() .collect(Collectors.groupingBy( Order::getCustomerId, Collectors.collectingAndThen( Collectors.maxBy(Comparator.comparing(Order::getOrderDate)), opt -> opt.map(Order::getCustomerId).orElse(null) ) )) .values().stream() .filter(Objects::nonNull) .collect(Collectors.toList());
方法3:使用toMap收集器(简洁版)
List<String> customerIds = new ArrayList<>( orders.stream() .collect(Collectors.toMap( Order::getCustomerId, Function.identity(), (o1, o2) -> o1.getOrderDate().isAfter(o2.getOrderDate()) ? o1 : o2 )) .values() ).stream() .map(Order::getCustomerId) .collect(Collectors.toList());
完整示例
List<Order> orders = Arrays.asList( new Order("C1", LocalDate.of(2023, 1, 10), 100.0), new Order("C1", LocalDate.of(2023, 2, 15), 150.0), new Order("C2", LocalDate.of(2023, 1, 5), 200.0), new Order("C2", LocalDate.of(2023, 3, 20), 250.0), new Order("C3", LocalDate.of(2023, 2, 1), 300.0) ); // 获取每个最新订单对应的客户ID List<String> latestOrderCustomerIds = orders.stream() .collect(Collectors.groupingBy( Order::getCustomerId, Collectors.maxBy(Comparator.comparing(Order::getOrderDate)) )) .values().stream() .flatMap(opt -> opt.map(Stream::of).orElseGet(Stream::empty)) .map(Order::getCustomerId) .collect(Collectors.toList()); System.out.println("拥有最新订单的客户ID: " + latestOrderCustomerIds);
输出结果
拥有最新订单的客户ID: [C1, C2, C3]
关键点说明
- 如果只需要ID而不需要整个对象,建议使用方法2,它更高效
map(Order::getCustomerId)
是提取ID的关键操作- 方法3使用
toMap
合并函数,适合简单的最大/最小值场景 - 根据需求可以替换
getCustomerId()
为任何其他字段的getter方法