Создание двумерного массива общих списков на Java - PullRequest
0 голосов
/ 31 марта 2012

Итак, я хочу создать двумерный массив общих списков, содержащих некоторые данные, которые меня интересуют (на сетке некоторого заданного размера),

private ArrayList<MyDataStruct>[][] gridData;

Когда я инициализирую этот массив, я иду,

gridData = (ArrayList<MyDataStruct>[][])new ArrayList[w][h];
for(int x=0; x<w; x++)
    for(int y=0; y<h; y++){
        gridData[x][y] = (ArrayList<MyDataStruct>)new ArrayList<MyDataStruct>(0);
        //other stuff, i.e. get data from somewhere, etc
    }

, и я получаю предупреждение unchecked cast.Мне было любопытно, почему это не безопасно для типов и что я могу сделать, чтобы сделать его безопасным (если не считать использование 2d-массива).Я понимаю, что смешивать массивы и дженерики не очень хорошо, но в этом случае я просто пишу это, чтобы провести некоторые эксперименты, поэтому я использую это вместо, скажем, списков списков списков, чтобы сэкономить себе время.Существуют ли другие более изящные подходы, которые позволят мне получить простой синтаксис для чтения / записи (то есть без вложенных списков), но также безопасны для типов?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 31 марта 2012

Единственный безопасный тип - это использование вложенных списков.

Из-за стирания типа вы не можете сделать new ArrayList<MyDataStruct>[w][h], потому что это в основном становится new ArrayList[w][h] ... и все становится сложным и быстрым, потому что массивы не ведут себя как дженерики.

Java считает String[] подклассом Object[], но ArrayList<String> не является подклассом ArrayList<Object>.Обычно массивы выдают ArrayStoreException, когда вы пытаетесь поместить элемент в массив, который не соответствует истинному типу массива, но из-за стирания типа он не может этого сделать, когда на изображении присутствуют обобщения.

Джош Блох приводит следующий пример в Effective Java:

// Why generic array creation is illegal - won't compile!
List<String>[] stringLists = new List<String>[1];
List<Integer> intList = Arrays.asList(42);
Object[] objects = stringLists;
objects[0] = intList;
String s = stringLists[0].get(0);

Единственный способ не допустить, чтобы весь этот код был полностью легален в Java, - это запретить создание универсального массива или, по крайней мере, пометить его какнебезопасно.

Тем не менее, IMO, умеренные накладные расходы при наборе List и выполнении его с помощью общих списков абсолютно оправдывают безопасность типов.

0 голосов
/ 31 августа 2013

Я попал сюда с той же проблемой (только некоторые эксперименты, подход "добейся цели").Вот решение, которое, кажется, работает для меня, используя отражение.

Обратите внимание, что оно на 100% не зависит от типа ячеек в массиве (может быть список, карта, что угодно).возможно, немного потрудившись, он также может не зависеть от количества измерений массива, но сегодня я хочу пожарить большую рыбу ...

private static <T>  T[][] makeArray(Class<T> componentType, int... dimentions) {
    return (T[][]) Array.newInstance(componentType, dimentions);
}

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

@Test
public void testMakeArray() throws Exception {
    @SuppressWarnings("unchecked")
    List<String>[][] arr = makeArray(List.class, 2, 3);

    Assert.assertEquals(2, arr.length);
    Assert.assertEquals(3, arr[0].length);

    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr[i].length; j++) {
            arr[i][j] = Arrays.asList("cell", "r="+i, "c="+j);
            System.out.print(arr[i][j] + "\t");
        }
        System.out.println("");
    }
}

он печатает:

[cell, r=0, c=0]    [cell, r=0, c=1]    [cell, r=0, c=2]    
[cell, r=1, c=0]    [cell, r=1, c=1]    [cell, r=1, c=2]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...