我尝试使用HashMap和Hastable以及对象列表作为键。 请参阅下面我的代码的简化版本,它不起作用。 当我调试这段代码时,我希望在 TestMap4 对象中有3个项目,但只有1个。
List<String> lst = new ArrayList<>();
lst.add("Hello");
lst.add("World");
Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst, 1);
testMap4.put(lst, 2);
testMap4.put(lst, 5);
当我将新项目放入HashMap对象时会发生什么?为什么它不起作用?
我通过下面这个新例子得到了相同的结果。 (每个List都有相同的2个字符串)
List<String> lst = new ArrayList<>();
lst.add("Hello");
lst.add("World");
List<String> lst2 = new ArrayList<>();
lst2.add("Hello");
lst2.add("World");
List<String> lst3 = new ArrayList<>();
lst3.add("Hello");
lst3.add("World");
Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst,1);
testMap4.put(lst2,2);
testMap4.put(lst3,5);
如果我只修改2个字符串中的1个字符,那就没问题
答案 0 :(得分:5)
您不理解HashMap
的概念。
您的问题是每次都使用相同的密钥。
testMap4.put(lst, 1); <----same key, different value
testMap4.put(lst, 2); <----same key, different value
testMap4.put(lst, 5); <----same key, different value
在Hashmap
中,存储在Hashmap
中的每个值都有一个key
,其中包含该特定值,每个值都唯一存储在Hashmap
关于HashMap
的重点:
1- HashMap包含基于密钥的值。
2-它只包含独特的元素。
3-它可能有一个空键和多个空值。
4-它没有订单。
示例强>
HashMap<Integer,String> hm=new HashMap<Integer,String>();
其次,如果在将任何列表插入地图后修改了任何列表,则使用可变对象(List<>
)作为键将导致未定义的行为。只有当条目首次插入到地图中时,才会根据List
的合同(请参阅Javadoc)计算哈希码。更改列表的内容将更改哈希代码,您将无法再找到该条目。
使用List<>
(或任何可变对象)作为HashMap<>
中的键是 Really Bad Idea™。
答案 1 :(得分:0)
它不起作用,因为您每次使用相同的键来存储不同的值,因为所有值都映射到相同的键,而hashmap只存储最后一个值,因为此值会覆盖以前的值。
答案 2 :(得分:0)
HashMap调用放在HashMap中的键对象上的hashCode()
方法。
由于您没有为您使用的密钥类(在您的情况下为List<>
)覆盖它,因此它会调用hashCode()
上的java.lang.Object
方法,该方法返回唯一的对象ID
当您将相同的对象放入地图三次时,它与您连续三次放入的密钥相同。
List<String> lst1 = new ArrayList<>();
lst.add("Hello");
lst.add("World");
List<String> lst2 = new ArrayList<>();
List<String> lst3 = new ArrayList<>();
Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst1, 1);
testMap4.put(lst2, 2);
testMap4.put(lst3, 5);
会在地图中为您提供三个条目。
如果您需要对列表内容使用HashCode以用作HashMap密钥,请查看:
static int java.util.Objects.hash(Object... values)
static boolean java.util.Arrays.equals(Object[] a, Object[] a2)
请勿忘记总是必须覆盖两种方法。 hashCode()
和 equals()
。如果你只覆盖其中一个,你会立刻掉线! ;)