如何在Java中初始化时将数组插入哈希表?

时间:2012-07-21 17:46:48

标签: java arrays hash initialization hashmap

我的hashmap初始化如下:

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

我想插入测试而无需初始化密钥:

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

但是,Java似乎不允许我这样做。如果我这样做就行了:

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

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

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

由于

4 个答案:

答案 0 :(得分:4)

是的,你可以这样写:

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

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

答案 1 :(得分:4)

在您的情况下,您必须使用

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

因为您注意到{{"a"}, {"a"}}

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

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

答案 2 :(得分:1)

您可以使用

tests.put(new String[][]{{"hello", "goodbye"},{"hi", "bye"}}, true);

答案 3 :(得分: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)

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

解决方案是将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放入地图之前创建List的深层副本(即复制“内部”列表以及“外部”列表)
  3. 对于第二个选项,它类似于:

    // 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);
    }