#java #generics
Вопрос:
У меня есть метод, который берет два массива и объединяет их с элементами в естественном порядке. Мне было интересно, можно ли сделать его универсальным, чтобы он мог принимать массивы любого типа и объединять их в массив того же типа?
Прямо сейчас я могу построить только массив 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;
}
Ответ №1:
Вы не можете создать массив универсального типа в Java, но вы можете использовать лямбду создателя:
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
параметр метода (вместо лямбды), а затем используйте (T[]) Array.newInstance(itemClass, a.length b.length)
его для создания нового массива.
Если вы хотите избежать дополнительных аргументов метода (например, лямбда-код создателя или класс элемента), вы можете использовать отражение для получения типа элемента массива:
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);
// ...
Ответ №2:
Если вы создадите mergedArray из типа из a, он может выглядеть следующим образом.
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);