3

我有一个哈希图初始化如下:

Hashmap<String[][], Boolean> tests = new Hashmap<String [][], Boolean>();

我想插入测试而不必初始化密钥:

tests.put({{"a"}, {"a"}}, true);

但是,Java 似乎不允许我这样做。如果我这样做,它会起作用:

String[][] hi = {{"a"}, {"a"}};
tests.put(hi, true);

有没有办法避免后者并让前者工作?

有人也可以解释这个错误背后的原因吗?

谢谢

4

4 回答 4

4

是的,你可以这样写:

tests.put(new String[][] {{"a"}, {"a"}}, true);

这通常被称为匿名数组即时数组。

于 2012-07-21T17:48:54.423 回答
4

在您的情况下,您将不得不使用

tests.put(new String[][]{{"a"}, {"a"}}, true);

因为正如你所注意到的{{"a"}, {"a"}}

String[][] hi = {{"a"}, {"a"}};

只能在创建对数组的引用时使用。

于 2012-07-21T17:49:48.490 回答
1

这几乎绝对不是你想要的。

Java 中的数组从它们的引用标识中获取它们的相等性和哈希码Object——也就是说,基于它们的引用标识。所以:

String[] a = { "hello" }; // create one array
String[] b = { "hello" }; // create a different array with the same contents
assert a != b; // the two references are to different objects
assert ! a.equals(b); // they're not equal
assert a.hashCode() != b.hashCode(); // neither are their hashes (probably)

a并且b不会相等,并且它们的哈希码几乎肯定不会相等,因为它们是不同的对象。这意味着,如果您使用数组作为哈希映射的键,您将无法使用键检索值,而是使用您创建它的确切键:任何其他数组都将具有不同的哈希码并且将不相等,因此不会被视为等效键。

解决方案是将 替换String[][]List<List<String>>. 列表根据其内容定义相等和哈希码,因此包含 的列表[ "hello" ]等于包含 的任何其他列表[ "hello" ]

List<String> x = Arrays.asList("hello");
List<String> y = Arrays.asList("hello");
assert x != y; // the two lists are different objects
assert x.equals(y); // but they're equal
assert x.hashCode() == y.hashCode(); // and so are their hash codes

现在您可以将列表用作键。请记住,一旦列表成为地图的键,就不允许更改值。这样做可能会破坏哈希映射,因为列表的哈希码会发生变化,但映射不会知道它,因此映射会在错误的哈希桶中查找它。

这里最简单的选择是:

  1. 确保没有其他人引用同一个 List 对象并且可能会更改它
  2. 在将其放入地图之前创建 List 的深层副本(即复制“内部”列表以及“外部”列表)

对于第二个选项,它会是这样的:

// copy the outer list
List<List<String>> outerCopy = new ArrayList<List<String>>( originalList );
ListIterator<List<String>> listIterator = outerCopy.listIterator();
while (listIterator.hasNext()) {
    // make a copy of the inner list
    List<String> innerCopy = new ArrayList<String>( listIterator.next() );
    listIterator.set(innerCopy);
}
于 2012-07-21T19:35:41.637 回答
1

您可以使用

tests.put(new String[][]{{"hello", "goodbye"},{"hi", "bye"}}, true);
于 2012-07-21T17:48:42.957 回答