这几乎绝对不是你想要的。
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
现在您可以将列表用作键。请记住,一旦列表成为地图的键,就不允许更改值。这样做可能会破坏哈希映射,因为列表的哈希码会发生变化,但映射不会知道它,因此映射会在错误的哈希桶中查找它。
这里最简单的选择是:
- 确保没有其他人引用同一个 List 对象并且可能会更改它
- 在将其放入地图之前创建 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);
}