的高效方法 ” />
本文將深入探討如何使用 Java 8 Stream API 將一個 List
核心思路
問題的關鍵在于如何處理嵌套的集合結構。我們需要將 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<Employee> 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<Trip> 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<String, List<Trip>> 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
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END