Как реализовать функцию для преобразования типичного типизированного массива в общий типизированный двумерный массив в java?

100
12

public static <T> T[][] toTwoDim(T[] array)

Подпись функции, как она выше..
Это типичная типизированная функция, которая может использоваться независимо от того, какой тип данных содержится в массиве.
обычно он получает массив и возвращает 2-мерный массив с его половинными элементами в первой строке, а вторую половину во второй строке.
Я понятия не имею, как реализовать его, потому что я не мог создать типичный типизированный двумерный массив внутри функции.
Кто-то помогает мне?
Спасибо!

спросил(а) 2021-01-19T16:14:08+03:00 6 месяцев, 1 неделя назад
1
Решение
64

Я играл с этим довольно много, и мое понимание, по причинам стирания стилей, заключается в том, что это не то, что возможно.


На основе других примеров создания массивов параметров типового типа кажется что-то вроде следующего кода, который должен работать, но в конечном счете он терпит неудачу только при возврате функции, где Object[][] нельзя передать в Integer[][]. Это было бы неудачно раньше, за исключением того, что IIRC исходный отбор (T[][]) в основном удаляется во время компиляции и действует для предотвращения предупреждения, поэтому он не имеет никакого реального эффекта.


@SuppressWarnings("unchecked")
public static <T> T[][] toTwoDim(T[] array){
int halflen = array.length / 2;

T[][] foo = (T[][]) new Object[2][];

foo[0] = (T[]) new Object[halflen];
foo[1] = (T[]) new Object[halflen];

for(int i = 0; i < halflen; i++){
foo[0][i] = array[i];
foo[1][i] = array[i+halflen];
}

System.out.println(Arrays.asList(foo[0]));
System.out.println(Arrays.asList(foo[1]));

return foo;
}

public static void main(String[] a){
Integer[] bar = {1,2,3,4};
Integer[][] foo = toTwoDim(bar);
System.out.println(Arrays.asList(foo[0]));
}

ответил(а) 2021-01-19T16:14:08+03:00 6 месяцев, 1 неделя назад
63

Я нашел идеальное решение:


@SuppressWarnings("unchecked")
public static <T> T[][] toTwoDim(T[] array) {
Class<T> ctype = (Class<T>) array.getClass().getComponentType();
int halfLength = array.length / 2;
T[][] ret = (T[][]) Array.newInstance(ctype, 2, 1);
T[] r1 = (T[]) Array.newInstance(ctype, halfLength);
T[] r2 = (T[]) Array.newInstance(ctype, array.length - halfLength);
ret[0] = r1;
ret[1] = r2;
for (int i = 0; i < halfLength; i++)
r1[i] = array[i];
for (int i = 0; i < array.length - halfLength; i++) {
r2[i] = array[i + halfLength];
}
return ret;
}

public static void main(String[] a) {
Integer[] bar = { 1, 2, 3, 4, 5 };
Integer[][] dims = toTwoDim(bar);
for (Integer[] r : dims) {
for (Integer d : r) {
System.out.print(d + " ");
}
System.out.println();
}
}

Выход:

1 2

3 4 5


общий тип функции 'toTwoDim' стирается, но тип элемента входящего массива может быть получен через отражение!

ответил(а) 2021-01-19T16:14:08+03:00 6 месяцев, 1 неделя назад
64

Это должно быть возможно.


Основной подход заключается в использовании java.lang.reflect.Array.newInstance(clazz, dimX, dimY) для создания экземпляра массива.

    Если вы хотите, чтобы базовый тип массива результатов был таким же, как базовый тип аргумента, затем используйте отражение, чтобы получить базовый тип из array.getClass().


    Если вы хотите, чтобы базовый тип массива результатов был <T>, вам нужно добавить дополнительный аргумент в toTwoDim, тип которого Class<T>, и использовать его для передачи объекта класса для желаемый массив базовый тип. (Тип erasure означает, что метод toTwoDim не может определить объект класса для <T> во время выполнения. Передача объекта класса в качестве аргумента является стандартным обходным решением.)


ответил(а) 2021-01-19T16:14:08+03:00 6 месяцев, 1 неделя назад
46

Вы можете сделать это, что не требует пресечения каких-либо предупреждений.


public static <T> T[][] toTwoDim(Class<T[][]> clazz, T[] array)  
{
int halfLength = array.length / 2;
T[][] ret = clazz.cast(Array.newInstance(clazz.getComponentType().getComponentType(), 2, halfLength + 1));
System.arraycopy(array, 0, ret[0], 0, halfLength);
System.arraycopy(array, halfLength, ret[1], 0, array.length - halfLength);
return ret;
}

ответил(а) 2021-01-19T16:14:08+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема