我编写了一个MergeSort实现,它应该对任何数据类型的数组进行排序。
我在这里面临两个问题。
由于编译器出错,无法将通用类型定义为数组 说' 无法创建T '的通用数组, 我已经跟踪了StackOverflow中其中一个线程中建议的kludge使用
T [] right =(T [])Array.newInstance(clazz,rightSize);
因此,使用运行时提供的类型信息,我们仍然可以实例化一个数组并将其强制转换回T [],尽管它仍然容易受到ClassCastException的影响,无论我们是否处理它。
还有其他有效且理想的方法来实现这一目标吗?
那么我是否需要为每个我想要排序的原始类型数组创建一个MergeSort类?
非常感谢任何帮助。 感谢。
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
public class MergeSort {
public <T> void sort(T[] values, Class<T> clazz, Comparator<T> comparator) {
if (values == null) {
throw new IllegalArgumentException("values is null.");
}
// recursion exit criteria.
if (values.length < 2) {
return;
}
// segregate the values array into 2 halves.
int median = values.length / 2;
int leftSize = median;
int rightSize = values.length - median;
// construct the left array.
T[] left = (T[]) Array.newInstance(clazz, leftSize);
for (int l = 0; l < leftSize; ++l) {
left[l] = values[l];
}
// construct the right array.
T[] right = (T[]) Array.newInstance(clazz, rightSize);
for (int r = 0; r < rightSize; ++r) {
right[r] = values[leftSize + r];
}
// recursively do merge sort on either side of the array.
sort(left, clazz, comparator);
sort(right, clazz, comparator);
// merges the left and right and keeps the intermediate
// values array sorted as it works it's way up.
_merge(values, left, right, comparator);
}
private <T> void _merge(T[] values, T[] left, T[] right, Comparator<T> comparator) {
int leftIndex = 0;
int rightIndex = 0;
int sortedIndex = 0;
while (leftIndex < left.length && rightIndex < right.length) {
int comparison = comparator.compare(left[leftIndex], right[rightIndex]);
if (comparison <= 0) {
values[sortedIndex] = left[leftIndex];
leftIndex++;
} else {
values[sortedIndex] = right[rightIndex];
rightIndex++;
}
sortedIndex++;
}
// Handle the left over elements if any in the left side
// and places them in the sorted array.
while (leftIndex < left.length) {
values[sortedIndex] = left[leftIndex];
leftIndex++;
sortedIndex++;
}
// Handle the left over elements if any in the right side.
// and places them in the sorted array.
while (rightIndex < right.length) {
values[sortedIndex] = right[rightIndex];
rightIndex++;
sortedIndex++;
}
}
public static void main(String[] args) {
Integer[] values = new Integer[] { 5, 0, 10, 4, 1, 8, 3, 9, 6, 2, 7 };
new MergeSort().sort(values, Integer.class, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
System.out.println(Arrays.toString(values));
}
}
答案 0 :(得分:4)
关于你的第一个问题:你可以使用
T[] newArray = (T[]) new Object[newSize];
您可以保证此演员表始终成功,新数组将始终只保留T
秒。因此,铸件被整流 1 。要取消unchecked cast
- 警告,请使用@SuppressWarnings("unchecked")
标记方法。
关于你的第二个问题:为了获得最佳表现,是的。您应该为每种基本类型提供一个实现。协方差和自动装箱不足以将int[]
转换为Integer[]
。
关于第三个问题:您可以实际重新使用旧数组,而不是为左右部分创建新数组,只需将左右传递作为递归调用的参数。有关实施,请参阅this github link。
对代码的评论:在Java中,方法名称应始终以小写字母开头。虽然我知道在C ++中使用_
启动私有方法很常见,但在Java中并非如此。
对您的问题的一些一般性评论:
1 java.util.ArrayList
使用类似的apporoach:支持数组是Object[]
,私有方法E elementData(int index)
将返回值强制转换为{{1} }} 子>