Java HashMap包含几个具有相同值的不同键?
我所做的很简单:我想创建一个Java HashMap包含几个具有相同值的不同键?,java,arraylist,hashmap,immutability,mutable,Java,Arraylist,Hashmap,Immutability,Mutable,我所做的很简单:我想创建一个HashMap,其中Pair作为键,ArrayList作为值。对是自定义类,包含元素l(左)和r(右) 起初,我是这样做的: Map<Pair, ArrayList<Integer>> hashmap = new HashMap<>(); ArrayList<String> stringList = new ArrayList<>(); stringList.add("a"); stringList.add(
HashMap
,其中Pair
作为键,ArrayList
作为值。对是自定义类,包含元素l
(左)和r
(右)
起初,我是这样做的:
Map<Pair, ArrayList<Integer>> hashmap = new HashMap<>();
ArrayList<String> stringList = new ArrayList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
stringList.add("a");
Pair<String, Integer> aPair = new Pair<>(" ", 1); // HERE will be changed!
for (String aString: stringList) {
aPair.setLeft(aString);
if (!hashmap.containsKey(aPair)){
hashmap.put(aPair, new ArrayList<Integer>());
}
hashmap.get(aPair).add(1);
}
for (Map.Entry<Pair, ArrayList<Integer>> entry: hashmap.entrySet()) {
out.println(entry.getKey().getLeft() + " " + entry.getKey().getRight() + " " + entry.getValue());
}
Map<Pair, ArrayList<Integer>> hashmap = new HashMap<>();
ArrayList<String> stringList = new ArrayList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
stringList.add("a");
for (String aString: stringList) {
Pair<String, Integer> aPair = new Pair<>(aString, 1); // HERE changed!
if (!hashmap.containsKey(aPair)){
hashmap.put(aPair, new ArrayList<Integer>());
}
hashmap.get(aPair).add(1);
}
for (Map.Entry<Pair, ArrayList<Integer>> entry: hashmap.entrySet()) {
out.println(entry.getKey().getLeft() + " " + entry.getKey().getRight() + " " + entry.getValue());
}
c 1 [1]
b 1 [1]
a 1 [1, 1]
但是,如果我将上述代码更改为以下代码:
Map<Pair, ArrayList<Integer>> hashmap = new HashMap<>();
ArrayList<String> stringList = new ArrayList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
stringList.add("a");
Pair<String, Integer> aPair = new Pair<>(" ", 1); // HERE will be changed!
for (String aString: stringList) {
aPair.setLeft(aString);
if (!hashmap.containsKey(aPair)){
hashmap.put(aPair, new ArrayList<Integer>());
}
hashmap.get(aPair).add(1);
}
for (Map.Entry<Pair, ArrayList<Integer>> entry: hashmap.entrySet()) {
out.println(entry.getKey().getLeft() + " " + entry.getKey().getRight() + " " + entry.getValue());
}
Map<Pair, ArrayList<Integer>> hashmap = new HashMap<>();
ArrayList<String> stringList = new ArrayList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
stringList.add("a");
for (String aString: stringList) {
Pair<String, Integer> aPair = new Pair<>(aString, 1); // HERE changed!
if (!hashmap.containsKey(aPair)){
hashmap.put(aPair, new ArrayList<Integer>());
}
hashmap.get(aPair).add(1);
}
for (Map.Entry<Pair, ArrayList<Integer>> entry: hashmap.entrySet()) {
out.println(entry.getKey().getLeft() + " " + entry.getKey().getRight() + " " + entry.getValue());
}
c 1 [1]
b 1 [1]
a 1 [1, 1]
为什么会这样?这是一个类似的问题。但情况仍然不同
编辑:正如@Eran在下面的评论中提到的,自定义的对
覆盖方法hashCode()
和equals()
@覆盖
public int hashCode(){返回left.hashCode()^right.hashCode();}
@凌驾
公共布尔等于(对象o){
如果(!(o instanceof Pair))返回false;
对pairo=(对)o;
返回this.left.equals(pairo.getLeft())&&
this.right.equals(pairo.getRight());
}
在第一个代码片段中,实际上您对map的每个条目都使用相同的key对象。您只需修改它的左值,但它仍然指向相同的内存地址。Map需要有唯一的密钥(每个密钥必须指向不同的内存地址),这就是为什么您需要为每个Map条目添加pair的新实例。您正在危险的水域中行走,因为您的密钥是可变的,请阅读此文为什么这不是一个好主意-
好吧,仅你的例子就说明了为什么这不是一个好主意。您在映射中添加一个键实例,然后对其进行修改,从而有效地修改了hashmap中的所有键值对。您的第一个代码片段不起作用,因为您正在对已在hashmap
中用作键的相同对实例进行变异。这允许相同的Pair
实例作为键出现在HashMap
的多个条目中(因为修改Pair
实例后计算的新hashCode
实例被映射到不包含任何条目的HashMap
的新存储桶中),并有效地破坏HashMap
您不应该对用作HashMap
键的实例进行变异(除非您在更新它之前将其从HashMap
中删除,并在以后将更新的版本放入映射中)
如果对象的hashCode()值可以根据其状态进行更改,那么
在基于哈希的应用程序中使用此类对象作为键时必须小心
集合,以确保在
它们被用作散列键。所有基于哈希的集合都假定
对象的哈希值在用作
输入集合中的键。如果密钥的散列码在
在一个集合中,一些不可预测和混乱的结果
我可以跟着。在实践中,这通常不是问题——事实并非如此
使用列表之类的可变对象作为
哈希映射
从这个是的。它们是超驰的@有没有一把map
刀,它的键可以更改?@ChangLiu钥匙可以更改,但您必须在更改前将其移除,更改后重新添加,以便地图将其存储在以后可以找到的位置。是的,我知道这一点。我想知道的是:你无法更新键
。@ChangLiu我不知道。