2

我想知道采用哪种方法来创建泛型的二维“类数组”(或数组)。

  1. 创建列表列表

    LinkedList<LinkedList<T>> myObject;
    
  2. 或者这个方法,更直观但是需要使用Refecltion来检索类型。

    T[] testArray = c.cast(Array.
            newInstance(c.getComponentType(), dim1, dim2));
    

这个想法是我有一个包含成员变量的类:

public class Board<T>
{
    T[][] array;

    public Board(int vertical_size, int horizontal_size)
    {
        array = new T[vertical_size][horizontal_size]; //which is not allowed because of the way that java implements Generics
    }
}

我应该采用上面列出的两种方法中的哪一种.. 还是有更好的方法来解决这个问题?

4

7 回答 7

2

您不需要 a T[][]- 您可以Object[][]轻松地使用 a(并T在需要时进行投射)。T如果您只允许实例填充数组,这应该没有问题。

事实上,如果你看一下,你会发现 anArrayList<T>是由 an Object[](不是 a T[])支持的,并且使用了类似的方法:

111     private transient Object[] elementData;

...

336     @SuppressWarnings("unchecked")
337     E elementData(int index) {
338         return (E) elementData[index];
339     }

如果您不需要动态调整板子大小,我想这种方法将比列表列表更有效。

于 2013-07-27T18:41:22.590 回答
1

如果要创建具有类型安全性的数组,只需执行以下操作。不确定每个人从哪里得到你做不到的概念:

import java.lang.reflect.Array;

public class Array2D<T> {
    private T[][] data;

    public Array2D(Class<T> clazz, int width, int height) {
        this.data = (T[][]) Array.newInstance(clazz, width, height);
    }

    public void putValue(int x, int y, T value) {
        data[x][y] = value;
    }

    public T getValue(int x, int y) {
        return data[x][y];
    }

    public static void main(String[] args) {
        Array2D<String> myStuff = new Array2D<String>(String.class, 10, 10);
        myStuff.putValue(3, 4, "Helloworld!");

        System.out.println(myStuff.getValue(3, 4));
    }
}

输出:

你好世界!

编辑:

如果您需要更高的性能,请考虑使用一维数组并将其视为 n 维数组。这是使用 android 设备时已知的改进,但前提是您不断访问数组。

此外,您可以强制调用者创建数组并完全避免使用反射。但是,除非您经常创建这些数组,否则不会产生显着差异,当 JVM 优化调用时更是如此。

import java.lang.reflect.Array;

public class Array2D<T> {
    private T[] data;
    private final int height;
    private final int width;

    public Array2D(Class<T> clazz, int width, int height) {
        // Using 1D array instead of 2D array
        this((T[]) Array.newInstance(clazz, width * height), width, height); 
    }

    public Array2D(T[] data, int width, int height) {
        this.data = data;
        this.width = width;
        this.height = height;
    }

    public void putValue(int x, int y, T value) {
        data[x * width + y] = value;
    }

    public T getValue(int x, int y) {
        return data[x * width + y];
    }

    public static void main(String[] args) {
        Array2D<String> myStuff = new Array2D<String>(String.class, 10, 10);
        myStuff.putValue(3, 4, "Helloworld!");

        System.out.println(myStuff.getValue(3, 4));

        // Force the caller to create the array
        Array2D<String> myOtherStuff = new Array2D<String>(new String[5 * 10], 5, 10);
        myOtherStuff.putValue(2, 7, "Goodbyeworld!");

        System.out.println(myOtherStuff.getValue(2, 7));
    }
}
于 2013-07-27T18:52:48.867 回答
1

这是我的想法(如果我理解了这个问题):

 class TwoDArray<T> {

    List<List<T>> list;

    public TwoDArray(int rows, int columns) {
    list = new ArrayList<List<T>>(rows);

    for(int i = 0; i<rows; i++) { 
        list.add(new ArrayList<T>(columns));
        for(int j = 0; j < columns; j++)
        list.get(i).add(j, null);
    }

    }

    public T getItem(int x, int y) {
    return list.get(x).get(y);
    }

    public void addItem(int x, int y, T e) {
    list.get(x).set(y, e);
    }

    public static void main(String[] args) {

    TwoDArray<String> bdimensional = new TwoDArray<String>(2, 2);
    bdimensional.addItem(1, 1, new String("hello"));
    bdimensional.addItem(0, 1, new String("bye"));  
    for(int i = 0; i < 2; i++) {
        for(int j = 0; j < 2; j++)
        System.out.println( i + " " + j + ": " + bdimensional.getItem(i,j));
    }

    }

}

输出是:

0 0: null
0 1: bye
1 0: null
1 1: hello

我不明白为什么我的大脑确信(T) nullwithnCopies会起作用。请查看便利实现

于 2013-07-27T18:57:15.280 回答
0

当涉及到泛型的使用时,Java 非常有限。您最好的选择是使用 2D 对象数组(例如 Object[][])

于 2013-07-27T18:50:57.553 回答
0

首先,绝对没有办法尝试实现 type 的 2D 数组T[][]

我想你自己已经回答了第一种类型的问题。但是另一种有趣的方式(如果可能的话)是:当您知道该类型T将始终是其他类型的子类型时。如果没有,总是有Object

interface SomeInterface{}

public class Board<T extends SomeInterface>
{
    SomeInterface[][] array;

    public Board(int horizontal_size, int vertical_size)
    {
        array = new SomeInterface[vertical_size][horizontal_size]; 
    }
}

然后你可以使用array你想要的二维数组。虽然我还是更喜欢ArrayList<ArrayList<T>>

于 2013-07-27T18:41:29.500 回答
0

没有好的解决方案,这是java的限制。

我更喜欢Object[][].

这最接近您想要对 2d 结构执行的操作。

于 2013-07-27T18:42:37.393 回答
0

有多种方法,但由于无论如何您都在包装实现,您可以简单地使用单个数组:

public class Board<T>
{
    private final Object[] array;
    private final int horizontal_size;

    public Board(int horizontal_size, int vertical_size)
    {
        array = new Object[vertical_size][horizontal_size];
        this.horizontal_size = horizontal_size;
    }

    // ...

    E get(int x, int y){
        // Check  if not out of bounds
        return (E) array[y * horizontal_size + x];
    }
}
于 2013-07-27T18:44:23.813 回答