内容纲要
引言
在日常开发中,我们经常会遇到这样一个问题:
给定两个整型数组,如何高效地合并它们,并对结果进行降序排序?
这个问题看似简单,但在不同场景下,可能有不同的实现方式。本文将全面介绍几种常见方法,并结合适用场景与性能特点做分析。
方法一:基础版(int[] + Arrays.sort + 倒序)
这是最直接的实现方式:先用 Arrays.sort
升序排序,再手动反转数组。
import java.util.Arrays;
public class MergeSortArrays1 {
public static void main(String[] args) {
int[] arr1 = {5, 2, 9};
int[] arr2 = {8, 1, 3};
int[] merged = new int[arr1.length + arr2.length];
System.arraycopy(arr1, 0, merged, 0, arr1.length);
System.arraycopy(arr2, 0, merged, arr1.length, arr2.length);
Arrays.sort(merged); // 升序排序
// 反转数组
for (int i = 0; i < merged.length / 2; i++) {
int temp = merged[i];
merged[i] = merged[merged.length - 1 - i];
merged[merged.length - 1 - i] = temp;
}
System.out.println(Arrays.toString(merged));
}
}
✅ 优点:适合 int[]
基础类型数组,容易理解。
⚠️ 缺点:需要额外的倒序操作。
方法二:Integer[] + Collections.reverseOrder
利用 Arrays.sort
的重载方法,直接传入比较器实现降序。
import java.util.Arrays;
import java.util.Collections;
public class MergeSortArrays2 {
public static void main(String[] args) {
Integer[] arr1 = {5, 2, 9};
Integer[] arr2 = {8, 1, 3};
Integer[] merged = new Integer[arr1.length + arr2.length];
System.arraycopy(arr1, 0, merged, 0, arr1.length);
System.arraycopy(arr2, 0, merged, arr1.length, arr2.length);
Arrays.sort(merged, Collections.reverseOrder()); // 直接降序
System.out.println(Arrays.toString(merged));
}
}
✅ 优点:代码最简洁,直接降序。
⚠️ 缺点:必须使用 Integer[]
(装箱,性能略差)。
方法三:Java 8 Stream 流式写法
如果你喜欢函数式风格,可以用流来处理。
import java.util.Arrays;
public class MergeSortArrays3 {
public static void main(String[] args) {
int[] arr1 = {5, 2, 9};
int[] arr2 = {8, 1, 3};
int[] merged = Arrays.stream(new int[][]{arr1, arr2})
.flatMapToInt(Arrays::stream)
.boxed()
.sorted((a, b) -> b - a) // 降序
.mapToInt(Integer::intValue)
.toArray();
System.out.println(Arrays.toString(merged));
}
}
✅ 优点:链式操作,代码简洁现代。
⚠️ 缺点:性能略低(装箱/拆箱)。
方法四:优先队列(最大堆)
适合数据量大且需要动态处理的情况。
import java.util.PriorityQueue;
public class MergeSortArrays4 {
public static void main(String[] args) {
int[] arr1 = {5, 2, 9};
int[] arr2 = {8, 1, 3};
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
for (int num : arr1) maxHeap.add(num);
for (int num : arr2) maxHeap.add(num);
while (!maxHeap.isEmpty()) {
System.out.print(maxHeap.poll() + " ");
}
}
}
✅ 优点:适合流式数据、边插入边取最大值的场景。
⚠️ 缺点:比一次性排序开销大。
方法五:双指针(如果数组已排序)
当两个数组本身已经是降序时,可以直接用双指针合并,避免再次排序。
import java.util.Arrays;
public class MergeSortArrays5 {
public static void main(String[] args) {
int[] arr1 = {9, 5, 2}; // 已经降序
int[] arr2 = {8, 3, 1}; // 已经降序
int[] merged = new int[arr1.length + arr2.length];
int i = 0, j = 0, k = 0;
while (i < arr1.length && j < arr2.length) {
if (arr1[i] >= arr2[j]) {
merged[k++] = arr1[i++];
} else {
merged[k++] = arr2[j++];
}
}
while (i < arr1.length) merged[k++] = arr1[i++];
while (j < arr2.length) merged[k++] = arr2[j++];
System.out.println(Arrays.toString(merged));
}
}
✅ 优点:时间复杂度 O(n),效率最高。
⚠️ 缺点:要求输入数组本身已排序。
方法对比
方法 | 使用场景 | 时间复杂度 | 优缺点 |
---|---|---|---|
方法一:基础版 | 普通 int[] ,简单需求 |
O(n log n) | 简单直观,但需要倒序 |
方法二:Collections.reverseOrder | Integer[] 数组 |
O(n log n) | 最简洁,但有装箱开销 |
方法三:Stream | Java 8+ 函数式风格 | O(n log n) | 代码现代,性能稍差 |
方法四:优先队列 | 数据流式处理 | O(n log n) | 适合大数据流,代码复杂 |
方法五:双指针 | 数组已排序 | O(n) | 最高效,但前提苛刻 |
总结
- 一般情况:推荐用 方法二(简洁)或 方法一(兼容
int[]
)。 - 喜欢函数式写法:用 方法三(流操作)。
- 实时数据流/边处理边输出:用 方法四(堆)。
- 数组本身已排序:首选 方法五(最优解)。