如何制作一个合并任何类型数组的泛型方法



我有一个方法,它接受两个数组,并按自然顺序将它们与元素合并。我想知道是否有可能使其通用,这样它就可以接受任何类型的数组,并将它们合并到同一类型的数组中?

现在我只能构建一个Object阵列

public static void main(String[] args) {
Integer[] i1 = {1, 3, 5, 7, 9};
Integer[] i2 = {2, 4, 6, 8, 10, 12, 14};
String[] s1 = {"A", "C", "E", "G"};
String[] s2 = {"B", "D", "F"};
System.out.println(Arrays.toString(mergeAndSortArrays(i1, i2)));
System.out.println(Arrays.toString(mergeAndSortArrays(s1, s2)));
}
public static<T extends Comparable<T>> Object[] mergeAndSortArrays(T[] a, T[] b) {
final Object[] merged = new Object[a.length + b.length];
int aPos = 0, bPos = 0, curIndex = -1;
while (++curIndex < merged.length) {
int comp = a[aPos].compareTo(b[bPos]);
merged[curIndex] = (comp < 0) ? a[aPos++] : b[bPos++];
if (aPos == a.length) {
while (bPos < b.length) {
merged[++curIndex] = b[bPos++];
}
break;
}
if (bPos == b.length) {
while (aPos < a.length) {
merged[++curIndex] = a[aPos++];
}
break;
}
}
return merged;
}

您不能在Java中创建泛型类型的数组,但可以使用创建者lambda:

public static<T extends Comparable<T>> T[] mergeAndSortArrays(
T[] a, 
T[] b, 
IntFunction<T[]> arrayCreator
) {
final T[] merged = arrayCreator.apply(a.length + b.length);
...
}

然后:

mergeAndSortArrays(i1, i2, Integer[]::new)
mergeAndSortArrays(s1, s2, String[]::new)

或者,使用Class<T> itemClass作为方法参数(而不是lambda(,然后使用(T[]) Array.newInstance(itemClass, a.length + b.length)创建新数组。

如果您想避免额外的方法参数(如创建者lambda或项类(,可以使用反射来检索数组项类型:

final Class<?> itemClass = a.getClass().getComponentType();
final T[] merged = (T[]) Array.newInstance(itemClass, a.length + b.length);

当然,您也可以使用现有的库来实现这一点,比如Apache Commons:

final T[] merged = org.apache.commons.lang3.ArrayUtils.addAll(a, b);
// ...

如果您从类型中创建mergedArray,它可能是这样的。

public static <T extends Comparable<T>> T[] mergeAndSortArrays(T[] a, T[] b) {
final T[] merged = (T[])Array.newInstance(a.getClass().getComponentType(), a.length + b.length);