| 方案 | 時間複雜度 | 實際耗時估算 | 致命傷 |
|---|---|---|---|
方案一:迴圈查 DB (N+1 問題)for(A a: listA) { B b = dao.getById(a.id); } | O(N) * DB_RTT | 500 * (網路延遲 1-5ms + DB 執行 0.5ms) ≈ 500ms - 2.5s | 網路往返 (RTT) 為主,資料庫連線池壓力大,極易超時。 |
方案二:雙層 for 記憶體比對for(A a: listA) for(B b: listB) if(a.id==b.aid) | O(N*M) = 250,000 | 純記憶體運算 ≈ 1ms - 5ms | 資料量增長為平方級 (1萬筆→1億次),不可擴展。 |
方案三:HashMap 索引 (最佳解)Map | O(N+M) = 1,000 | 建 Map + 查找 ≈ 0.5ms - 2ms | **線性複雜度,記憶體換速度,完美支援百萬級資料。** |
// 1. 一次性查出所有需要的數據 (2 次 DB 交互)
List listA = dao.selectAllA(); // SELECT * FROM A
List listB = dao.selectAllB(); // SELECT * FROM B
// 2. 建立 HashMap 索引 (Key 為關聯鍵,Value 為對象或所需字段)
// 若 A 唯一:Map mapA = new HashMap<>();
// 若 A 可能重複 (一對多):Map> mapA = new HashMap<>();
Map mapA = new HashMap<>(listA.size() * 2); // 預估容量避免擴容
for (A a : listA) {
mapA.put(a.getId(), a); // 假設 id 唯一
}
// 3. 遍歷 B 直接 O(1) 命中
List results = new ArrayList<>();
for (B b : listB) {
A a = mapA.get(b.getAid());
if (a != null) {
Map item = new HashMap<>();
item.put("A", a.getName());
item.put("B", b.getTime());
results.add(item); // 或直接組裝 DTO
}
// else: B 找不到對應 A,視業務決定是否保留
}
// 4. 若需包含「無 B 對應的 A」,再遍歷 mapA.values() 檢查是否已被引用
// (可用 Set matchedIds 記錄)
**最快的代碼是不寫代碼,讓資料庫做關聯。**
SELECT a.name, b.time
FROM A a
LEFT JOIN B b ON a.id = b.a_id
-- 可加 WHERE 條件
-- 若需分頁:LIMIT offset, size