简体   繁体   English

用Java创建一个通用列表的2D数组

[英]Making a 2D array of generic lists in Java

So - I want to make a 2D array of generic lists containing some data I am interested in (on a grid of of some set size), 所以 - 我想创建一个包含我感兴趣的一些数据的通用列表的二维数组(在一些设置大小的网格上),

private ArrayList<MyDataStruct>[][] gridData;

When I initialize this array, I go, 当我初始化这个数组时,我去了,

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
    }

and I get a unchecked cast warning. 我得到一个unchecked cast警告。 Was curious about why this is not type safe and what I can do to make it type safe (short of switching out of using a 2d array). 很好奇为什么这不是类型安全的,我可以做些什么使其类型安全(没有切换使用2d阵列)。 I understand that it's not very good to mix arrays and generics, but in this case I'm just writing this to run some experiments, so i'm using this instead of say lists of lists lists to save myself some time. 我知道混合数组和泛型并不是很好,但在这种情况下我只是写这个来运行一些实验,所以我使用它而不是列出列表列表以节省一些时间。 Are there any other more elegant approaches that let's me get away with easy to read/write syntax (ie no nested lists), but are also type safe? 是否还有其他更优雅的方法让我能够轻松读取/写入语法(即没有嵌套列表),但也是类型安全的?

Thanks! 谢谢!

The only type-safe option is to use nested lists. 唯一的类型安全选项是使用嵌套列表。

Because of type erasure, you can't do new ArrayList<MyDataStruct>[w][h] , because that basically becomes new ArrayList[w][h] ...and things get complicated and hairy, fast, because arrays don't behave like generics. 由于类型擦除,你不能做new ArrayList<MyDataStruct>[w][h] ,因为它基本上变成了new ArrayList[w][h] ...而且事情变得复杂多毛,快速,因为数组不要牛逼表现得像仿制药。

Java considers String[] to be a subclass of Object[] , but ArrayList<String> isn't a subclass of ArrayList<Object> . Java认为String[]Object[]的子类,但ArrayList<String>不是ArrayList<Object>的子类。 Normally, arrays throw an ArrayStoreException when you try to put an element into an array that doesn't match the array's true type, but because of type erasure, it can't do that when generics are in the picture. 通常,当您尝试将元素放入与数组的真实类型不匹配的数组时,数组会抛出ArrayStoreException ,但由于类型擦除,当泛型出现在图片中时,它不能这样做。

Josh Bloch gives the following example in Effective Java: Josh Bloch在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);

The only way to prevent all this code from being entirely legal in Java is to ban the generic array creation, or at least mark it as unsafe. 防止所有这些代码在Java中完全合法的唯一方法是禁止通用数组创建,或者至少将其标记为不安全。

That said, IMO, the moderate overhead of typing out List and doing it with generic lists is absolutely worth the type safety. 也就是说,IMO,键入List并使用通用列表进行操作的适度开销绝对值得类型安全。

I got here with the same problem (just some experiments, "get things done" approach). 我遇到了同样的问题(只是一些实验,“完成任务”的方法)。 Here is a solution that seems to work for me, using reflection. 这是一个似乎对我有用的解决方案,使用反射。

note that it is 100% agnostic to the type of the cells in the array (can be list, map, anything). 请注意,它与数组中的单元格类型100%无关(可以是列表,地图,任何内容)。 perhaps with a little more work it can also be agnostic to the # of dimensions of the array, but I've bigger fish to fry today... 也许还有一点点工作,它也可以与阵列的尺寸相关联,但我今天要炒更大的鱼...

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

attached below is a test method. 下面附有一种测试方法。 to keep the type of the array generic I had to ugly-cast here. 保持数组的类型通用我不得不在这里丑陋。 this can be handled in another wrapping method to keep client code nice and clean: 这可以在另一个包装方法中处理,以保持客户端代码良好和干净:

@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("");
    }
}

it prints: 它打印:

[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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM