Java中动态数组的声明

7

有人能告诉我这个Java声明中的错误吗:String[][] t=new String[15][15]; 这行代码是可以正常工作的。如果我使用 String[][] t=new String[][]; ,因为我不确定我需要在t中存储多少值,所以我需要将变量t声明为动态的。

6个回答

8
使用ArrayList(或其他可以处理任意数量对象的数组对象)。Java数组总是具有固定长度,因为一些内存将被保留用于该数组。
ArrayList也会创建这样的数组来存储对象。如果您添加的对象超过了当前保留的数组大小,则ArrayList将创建一个新的更大的数组(如果我没记错,增加50%)。还有一些其他实现方法略有不同(例如,当数组已满时,它们会创建原始数组的100%的新数组)。如果对性能真的很重要,那么可以研究一下这个。
ArrayList<ArrayList<String> t = new ArrayList<ArrayList<String>();

void fill() {
    ArrayList<String> t2 = new ArrayList<String>();
    t2.add("somestring");
    String s = "someotherstring";
    t2.add(s);
    t.add(t2);
}

Java数组始终具有固定长度,而不是最大长度。其中一些条目可能为空。 - DJClayworth
1
虽然这是可能的,但你需要创建一个 (ArrayList of String) 的 ArrayList,并且s = t[3][12];变成了s = t.get(3).get(12); - Stephen P
我能在数组列表中添加多维吗?我有一个键和一个值,我将键存储在数组[0][0]中,将值存储在[0][1]中,就像一个键有多个值一样... - raju
2
如果你有一个键和一个值,你可以使用HashMap,HashMap<String, String> hashMap = new HashMap<String, String>(); - Mark Baijens
如果你要用数组作为键/值对,那么在我看来,Baijens上面的答案最好。 - ChadNC

4
如果您不知道需要多大,只需将其声明为
String[][] t;

一旦您知道它需要有多大,您就可以在尝试使用数组之前进行操作。

t = new String[15][15];

如果您不确定数组需要多大,您需要使用类似于列表的列表(List of Lists)。

List<List<String>> t = new ArrayList<List<String>>;

public void add(String str, int row, int col) {
    while (row >= t.size())
        t.add(new ArrayList<String>());

    List<String> row_list = t.get(row);
    while (col >= row_list.size())
        row_list.add("");

    row_list.set(col, str);
}

如果我使用 String[][] t = null;,在使用t[0][0] = "ana"时会出现异常错误,错误信息为“Exception in thread "main" java.lang.NullPointerException”。 - raju
@raju:在你发现需要的维度之后,但在t[0][0] =赋值之前,你仍然需要执行t = new String[sizeX][sizeY]; - Stephen P

1
在Java中,数组对象始终具有固定的长度。一旦您分配了它们,就无法更改它们的大小。可以使数组变量指向不同大小的不同数组对象。因此,您可以分配以下内容:
String[][] t;

可以先创建一个不指向任何对象的指针,然后一旦知道大小,再分配一个对象:

int n1,n2;
// calculate n1,n2
t = new String[n1][n2];

如果您需要一个大小可以改变的结构,最好使用ArrayList,它可以动态调整大小。


1

将其声明为 String [][]t = null;

并在获得实际长度后使用重新初始化它。

t=new String[x][y];

最佳实际应用方式。 - Simmant

0

已经有几个很好的答案了,但是在Mark Baijens的答案的评论中透露出了这个问题的目的是raju需要一个键到多值的映射

Mark回复该评论时建议使用HashMap<String, String> hashMap = new HashMap<String, String>();,但这仅适用于单个键值对。

raju需要的是一个

Map<String, Collection<String>> t
    = new HashMap<String, List<String>>();

为一个键添加第一个值需要对该桶初始化一个List,而添加其他值则需要获取现有的列表并添加新值。

请注意,我在声明中使用了Collection<String>,因此如果值的顺序很重要,则可以是List,或者如果要防止在同一个键下出现重复值,则可以是Set。

这可能最好作为一个类本身来实现,也许

public class MultiValueMap<K, V> extends Map<K, V>
{
    ...
}

因此,在第一个put(key, value)上初始化列表和随后的.add(value)到列表中的操作可以在实现中隐藏。


0

正如bemace所说,仅仅因为你声明了变量并不意味着你必须立即初始化它。

正如Mark所说,数组有固定的大小。一旦一个数组被初始化(而不是声明,初始化),它就有了固定的大小。

因此,有两种可能性:

要么在开始使用数组之前,你将知道数组需要多大,这种情况下,你可以像bemace建议的那样简单地延迟初始化。

要么在开始使用数组之前,你不知道它需要多大,这种情况下,你需要使用动态大小的数据结构。请查看Java Collections API:

教程 API参考


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