如何在Java中创建一个二维数组

144
假设

我有5个字符串数组对象:

String[] array1 = new String[];
String[] array2 = new String[];
String[] array3 = new String[];
String[] array4 = new String[];
String[] array5 = new String[];

我想要另一个数组对象包含这5个字符串数组对象。我该怎么做?我能将其放入另一个数组中吗?


56
新手提出的问题可能是很严肃的,实际上它们经常是这样。 :-) - T.J. Crowder
5
相关问题,对于了解内存对齐方式的人来说答案并不明显。 +1 - Benj
4个回答

184

就像这样:

String[][] arrays = { array1, array2, array3, array4, array5 };
或者
String[][] arrays = new String[][] { array1, array2, array3, array4, array5 };

(后一种语法可以用于除变量声明之外的赋值操作,而较短的语法仅适用于声明。)


1
你能进一步解释一下第二个语法是做什么的吗?我有点不太清楚。 - Terence Ponce
5
它和第一个做的一样:它创建了一个字符串数组引用的数组,初始化为array1、array2、array3、array4和array5的值 - 每个值本身都是一个字符串数组引用。 - Jon Skeet
1
快速提问:如果我不知道会创建多少个数组对象,那么在运行时我该如何做到这一点? - Terence Ponce
1
@Terence:你能给一个更具体的例子吗?当你在编译时指定初始值时,你是知道大小的。你是指像 new String[10][] 这样的东西吗? - Jon Skeet
@Terence,你可以写出类似这样的代码:String[][] arrays = { {"A", "1"}, {"B", "2"}, {"C", "3"}, {"D", "4"}, {"E", "5"} }; - Ikem Krueger
显示剩余4条评论

86
尝试
String[][] arrays = new String[5][];

1
这个更加灵活。 - hetaoblog
你不应该在数组中定义固定的大小吗? - Filip
@Filip,它被固定为5。设置下一个级别会预先分配它们,但这可能是无用的,因此可以更改设置。 - Peter Lawrey
8
如何向数组中插入数据?如果是动态数据呢? - praxmon
2
@PrakharMohanSrivastava 你可以单独设置元素: arrays[0] = new String[] {"a", "b", "c"} 或者使用临时列表:<pre><code> List<String[]> myList = new ArrayList<>(); myList.add(new String[]{"a", "b", "c"}); myList.add(new String[]{"d", "e", "f"}); myList.toArray(arrays); </code></pre> - kntx

31
虽然有两个很好的答案告诉你如何做,但我觉得还缺少另一个答案:在大多数情况下,你根本不应该这样做。
数组很麻烦,在大多数情况下,你最好使用集合 API
使用集合,你可以添加和删除元素,并且有专门用于不同功能的集合(基于索引的查找、排序、唯一性、FIFO 访问、并发等)。
当然,了解数组及其用法是好的和重要的,但在大多数情况下,使用集合可以使 API 更易于管理(这就是为什么像Google Guava这样的新库几乎不使用数组)。
所以,对于你的场景,我更喜欢使用列表的列表,并使用 Guava 创建它:
List<List<String>> listOfLists = Lists.newArrayList();
listOfLists.add(Lists.newArrayList("abc","def","ghi"));
listOfLists.add(Lists.newArrayList("jkl","mno","pqr"));

比String[][]稍微复杂一些,但是允许更多的操作,例如连接数据。然而,您的解决方案不能确保数据的大小,这可能会产生问题。 - Benj
1
@Benj 如果有必要,总是可以编写一个只接受特定数量项目的List装饰器。 - Sean Patrick Floyd
精确地说,装饰器/包装器是确保一致性的好方法。因此,我们所讨论的方式比简单的数组要复杂得多。我做的是一个小型实用类Array2D<T>,它封装了一些基本方法,如exists(...)等。我在下面发布了这个类。 - Benj

6

在我们与Sean Patrick Floyd的评论中提到了一个类:我使用了一种需要WeakReference的特殊方式,但您可以轻松地将其更改为任何对象。

希望这能有助于某个人的某一天 :)

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Queue;


/**
 *
 * @author leBenj
 */
public class Array2DWeakRefsBuffered<T>
{
    private final WeakReference<T>[][] _array;
    private final Queue<T> _buffer;

    private final int _width;

    private final int _height;

    private final int _bufferSize;

    @SuppressWarnings( "unchecked" )
    public Array2DWeakRefsBuffered( int w , int h , int bufferSize )
    {
        _width = w;
        _height = h;
        _bufferSize = bufferSize;
        _array = new WeakReference[_width][_height];
        _buffer = new LinkedList<T>();
    }

    /**
     * Tests the existence of the encapsulated object
     * /!\ This DOES NOT ensure that the object will be available on next call !
     * @param x
     * @param y
     * @return
     * @throws IndexOutOfBoundsException
     */public boolean exists( int x , int y ) throws IndexOutOfBoundsException
    {
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ y = " + y + "]" );
        }
        if( _array[x][y] != null )
        {
            T elem = _array[x][y].get();
            if( elem != null )
            {
            return true;
            }
        }
        return false;
    }

    /**
     * Gets the encapsulated object
     * @param x
     * @param y
     * @return
     * @throws IndexOutOfBoundsException
     * @throws NoSuchElementException
     */
    public T get( int x , int y ) throws IndexOutOfBoundsException , NoSuchElementException
    {
        T retour = null;
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ y = " + y + "]" );
        }
        if( _array[x][y] != null )
        {
            retour = _array[x][y].get();
            if( retour == null )
            {
            throw new NoSuchElementException( "Dereferenced WeakReference element at [ " + x + " ; " + y + "]" );
            }
        }
        else
        {
            throw new NoSuchElementException( "No WeakReference element at [ " + x + " ; " + y + "]" );
        }
        return retour;
    }

    /**
     * Add/replace an object
     * @param o
     * @param x
     * @param y
     * @throws IndexOutOfBoundsException
     */
    public void set( T o , int x , int y ) throws IndexOutOfBoundsException
    {
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (set) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (set) : [ y = " + y + "]" );
        }
        _array[x][y] = new WeakReference<T>( o );

        // store local "visible" references : avoids deletion, works in FIFO mode
        _buffer.add( o );
        if(_buffer.size() > _bufferSize)
        {
            _buffer.poll();
        }
    }

}

使用示例:

// a 5x5 array, with at most 10 elements "bufferized" -> the last 10 elements will not be taken by GC process
Array2DWeakRefsBuffered<Image> myArray = new Array2DWeakRefsBuffered<Image>(5,5,10);
Image img = myArray.set(anImage,0,0);
if(myArray.exists(3,3))
{
    System.out.println("Image at 3,3 is still in memory");
}

5
感谢您的努力,但:与其将int字段初始化为-1并在构造函数中重新分配它们,您应该将它们设置为final,并仅在构造函数中进行赋值。 - Sean Patrick Floyd
1
@Sean:我修改了代码(发布了一个新的,包括你明智的评论,“无GC缓冲区”)。 - Benj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接