給定兩個數組 arr1, arr2,求 **在 arr2 中但不在 arr1 中的元素** (即 arr2 - arr1 差集)。保留 arr2 的順序與重複性 (視業務而定)。
public static List diffList(T[] arr1, T[] arr2) {
List list1 = Arrays.asList(arr1); // O(1) 轉換,底層數組
List diff = new ArrayList<>();
for (T t : arr2) {
if (!list1.contains(t)) diff.add(t); // contains 為 O(n) 線性查找
}
return diff;
}
// 測試
diffList(new Integer[]{1,2,3}, new Integer[]{1,2,3,4}); // [4]
缺點:大數組時性能差,contains 走 equals 比較。
public static List diffSet(T[] arr1, T[] arr2) {
Set set1 = new HashSet<>(Arrays.asList(arr1)); // O(n) 建立
List diff = new ArrayList<>();
for (T t : arr2) {
if (!set1.contains(t)) diff.add(t); // O(1) 查找
}
return diff;
}
優點:時間複雜度線性,適合萬級以上數據。
注意:要求元素正確實現 hashCode()/equals()。
public static List diffStream(T[] arr1, T[] arr2) {
Set set1 = new HashSet<>(Arrays.asList(arr1));
return Arrays.stream(arr2)
.filter(t -> !set1.contains(t))
.collect(Collectors.toList());
}
public static int[] diffPrimitive(int[] arr1, int[] arr2) {
// 使用 IntSet (如 fastutil) 或排序雙指針
Arrays.sort(arr1); // O(n log n)
List diff = new ArrayList<>();
for (int v : arr2) {
if (Arrays.binarySearch(arr1, v) < 0) diff.add(v); // O(log n)
}
return diff.stream().mapToInt(i -> i).toArray();
}
| 需求 | 實現 |
|---|---|
| 保留 arr2 順序、保留重複 | 上述所有方法默認行為 |
| 保留順序、去重 | 加 LinkedHashSet 過濾 diff |
| 不保留順序、去重 | 直接 set2.removeAll(set1) |