给定一个订单类,例如:
@ToString
@AllArgsConstructor
@Getter
static class Order {
long customerId;
LocalDate orderDate;
}
Run Code Online (Sandbox Code Playgroud)
和订单列表:
List<Order> orderList = List.of(new Order(1, LocalDate.of(2020,Month.APRIL,21)),
new Order(1, LocalDate.of(2021,Month.APRIL,21)),
new Order(1, LocalDate.of(2022,Month.APRIL,21)),
new Order(2, LocalDate.of(2020,Month.APRIL,21)),
new Order(2, LocalDate.of(2021,Month.APRIL,21)),
new Order(3, LocalDate.of(2020,Month.APRIL,21)),
new Order(3, LocalDate.of(2022,Month.APRIL,21)),
new Order(4, LocalDate.of(2020,Month.APRIL,21)));
Run Code Online (Sandbox Code Playgroud)
我需要获得一份清单,customerId其中列出了最后一次orderDate超过 6 个月的情况。所以对于上面的例子[2,4]。我的想法是首先按 分组customerId,第二个地图到最后orderDate,第三个过滤那些超过 6 个月的地图。我陷入了如何将最近的订单映射到单个订单的第二步orderDate
第一步
Map<Long, List<Order>> grouped =
orderList.stream()
.collect(Collectors.groupingBy(Order::getCustomerId));
Run Code Online (Sandbox Code Playgroud)
第二步(卡在这里如何更改上述内容以仅获取一项作为值)
Map<Long, Order> grouped =
orderList.stream()
.collect(Collectors.groupingBy(Order::getCustomerId, ???));
Run Code Online (Sandbox Code Playgroud)
甚至更好
Map<Long, LocalDate> grouped =
orderList.stream()
.collect(Collectors.groupingBy(Order::getCustomerId, ???));
Run Code Online (Sandbox Code Playgroud)
我尝试过使用Collectors.mapping(),Collectors.reducing()但Collectors.maxBy()有很多编译错误。
使用Collectors.toMap收集器获取按客户 ID 列出的订单的地图。之后,您可以仅过滤 6 个月以上的订单。
参见下面的实现:
import java.time.LocalDate;
import java.time.chrono.ChronoLocalDate;
import java.util.List;
import java.util.Optional;
import java.util.Collections;
import java.util.Objects;
import java.util.Comparator;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
Run Code Online (Sandbox Code Playgroud)
public static List<Long> getCustomerIdsOfOrdersOlderThanSixMonths(final List<Order> orderList) {
return Optional.ofNullable(orderList)
.orElse(Collections.emptyList())
.stream()
.filter(o -> Objects.nonNull(o) && Objects.nonNull(o.getOrderDate()))
.collect(Collectors.toMap(
Order::getCustomerId,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(Order::getOrderDate))))
.values()
.stream()
.filter(o -> o.getOrderDate()
.plusMonths(6)
.isBefore(ChronoLocalDate.from(LocalDate.now())))
.map(Order::getCustomerId)
.collect(Collectors.toList());
}
}
Run Code Online (Sandbox Code Playgroud)
List<Long> customerIds = getCustomerIdsOfOrdersOlderThanSixMonths(orderList);
// [2, 4]
Run Code Online (Sandbox Code Playgroud)