的高效方法
" />
核心思路
问题的关键在于如何处理嵌套的集合结构。我们需要将 Trip 对象中的 Employee 列表扁平化,以便能够基于 empId 进行分组。这可以通过引入一个辅助对象来实现,该对象同时持有 empId 和 Trip 实例的引用。
辅助对象:TripEmployee (Java 16+ record)
从 Java 16 开始,可以使用 record 关键字来简洁地定义一个不可变的数据类,非常适合作为辅助对象。
public record TripEmployee(String empId, Trip trip) {}如果使用 Java 8,则需要创建一个普通的 class。
立即学习“Java免费学习笔记(深入)”;
Java 8 实现 (class)
public class TripEmployee {
private String empId;
private Trip trip;
public TripEmployee(String empId, Trip trip) {
this.empId = empId;
this.trip = trip;
}
public String getEmpId() {
return empId;
}
public Trip getTrip() {
return trip;
}
}代码实现
以下是使用 Stream API 实现转换的代码示例:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
public class TripMappingExample {
@Data
@NoArgsConstructor
@AllArgsConstructor
static class Trip {
private Date startTime;
private Date endTime;
List empList;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
static class Employee {
private String name;
private String empId;
}
public record TripEmployee(String empId, Trip trip) {}
public static void main(String[] args) {
// 示例数据
List trips = new ArrayList<>();
// 创建一些 Employee 对象
Employee emp1 = new Employee("Alice", "E123");
Employee emp2 = new Employee("Bob", "E456");
Employee emp3 = new Employee("Charlie", "E123"); // 故意重复一个 empId
// 创建包含 Employee 列表的 Trip 对象
Trip trip1 = new Trip(new Date(), new Date(), List.of(emp1, emp2));
Trip trip2 = new Trip(new Date(), new Date(), List.of(emp2, emp3));
trips.add(trip1);
trips.add(trip2);
// 使用 Stream API 进行转换
Map> empMap = trips.stream()
.flatMap(trip -> trip.getEmpList().stream()
.map(emp -> new TripEmployee(emp.getEmpId(), trip)))
.collect(Collectors.groupingBy(
TripEmployee::empId,
Collectors.mapping(TripEmployee::trip,
Collectors.toList())));
// 打印结果
empMap.forEach((empId, tripList) -> {
System.out.println("Employee ID: " + empId);
tripList.forEach(trip -> System.out.println(" Trip: " + trip));
});
}
} 代码解释
- trips.stream(): 创建 Trip 对象的 Stream。
-
flatMap(trip -> trip.getEmpList().stream().map(emp -> new TripEmployee(emp.getEmpId(), trip))): 对于每个 Trip 对象,获取其 Employee 列表,并将其转换为 Stream
。然后,使用 map 操作将每个 Employee 对象转换为 TripEmployee 对象,其中包含 empId 和原始的 Trip 对象。flatMap 将所有这些 Stream 合并成一个单一的 Stream 。 - collect(Collectors.groupingBy(TripEmployee::empId, Collectors.mapping(TripEmployee::trip, Collectors.toList()))): 使用 groupingBy 收集器,根据 TripEmployee 对象的 empId 进行分组。mapping 收集器作为 groupingBy 的下游收集器,将每个分组中的 TripEmployee 对象转换为 Trip 对象,并将它们收集到一个列表中。
注意事项
- 确保项目中包含 Lombok 依赖,以便使用 @Data, @NoArgsConstructor, @AllArgsConstructor 等注解。
- 如果使用 Java 8,请将 record 替换为等效的 class 实现。
- 如果 empId 为 null 或空字符串,则 groupingBy 操作可能会导致 NullPointerException。在实际应用中,请根据需要添加空值检查。
总结
本文提供了一种使用 Java 8 Stream API 将 List










