1. 需求
今天一个同学让我帮他写一个归并排序和快速排序的代码。我首先想到使用泛型,这样就可以不用限制非得是int型数组。
2. 实现
- 归并排序
// 归并排序,分为两个过程:
// 1.分治递归
// 2.合并
public <T> void mergeSort1(T[] nums, int to, int from){
if(from - to < 2) return;
int mid = (to + from) >>> 1;
mergeSort1(nums, to, mid);
mergeSort1(nums, mid, from);
merge1(nums, to, from);
}
public <T> void merge1(T[] nums, int to, int from){
// 这个地方不能用泛型T声明一个数组
Object[] temp = new Object[from - to];
int index = 0;
int mid = (to + from) / 2, i = to, j = mid;
while (i < mid && j < from){
Comparable<T> o1 = (Comparable<T>) nums[i];
if(o1.compareTo(nums[j]) < 0) temp[index++] = nums[i++];
else temp[index++] = nums[j++];
}
while (i < mid) temp[index++] = nums[i++];
while (j < from) temp[index++] = nums[j++];
for (int k = to; k < from; k++) {
nums[k] = (T)temp[k - to];
}
}
使用了泛型方法和参数。但是里面有几个问题,一个是泛型类型T不能用来声明新的数组,因此temp数组使用的Object;二是泛型类对象没有compareTo()方法,因此要进行类型转换;三是temp数组向nums数组赋值时要进行类型转换。
- 快速排序
// quickSort分为两个过程
// 1.划分
// 2.分治递归
public <T> void quickSort1(T[] nums, int to, int from){
if(from - to < 2) return;
// 划分
int part = partition1(nums, to, from);
// 递归
quickSort1(nums, to, part);
quickSort1(nums, part + 1, from);
}
public <T> int partition1(T[] nums, int to, int from){
T privot = nums[to];
int i = to, j = from - 1;
while (i < j){
// 找到一个小于枢轴的数
while (((Comparable<T>)nums[j]).compareTo(privot) >= 0 && i < j) j--;
nums[i] = nums[j];
// 找到一个大于枢轴的数
while (((Comparable<T>)nums[i]).compareTo(privot) <= 0 && i < j) i++;
nums[j] = nums[i];
}
nums[i] = privot;
return i;
}
3. 那些容易踩到的坑
- 不能使用泛型直接new一个数组。此时可以new一个Object数组代替,然后在使用时,对数组中的元素进行类型转换;
- 不能直接对数组进行强制类型转换,只能逐个元素进行。此时可以使用Array.newInstance(componentTye, length)申请数组空间,然后这样就可以直接对数组进行类型转换为我们想要的类型。
public < E > E[] sample(E[] array, int k){
int len = array.length;
if (len < k || k < 0){
System.out.println("k值大于数组长度或者k值为负");
//泛型数组的开辟如下
return (E[]) Array.newInstance(array.getClass().getComponentType(), 0);
}
java中数组类型和元素类型是不一样的:
System.out.println(Array.newInstance(String.class, 1).getClass());
//结果是:class [Ljava.lang.String;
//可以看到多了半个括号一个分号
System.out.println(Array.newInstance(String.class, 1).getClass().getComponentType());
//结果是:class java.lang.String