取出分组后每组最大值对象的ID
如果只需要获取这些对象的ID(或其他特定字段),而不是整个对象,可以采用以下方法:
方法1:先获取对象再提取ID
java
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(更高效)
java
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收集器(简洁版)
java
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());
完整示例
java
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方法