Java—将HashMap与列表一起使用<&燃气轮机;作为关键

Java—将HashMap与列表一起使用<&燃气轮机;作为关键,java,arraylist,hashmap,Java,Arraylist,Hashmap,我尝试使用HashMap和HastTable,并将对象列表作为键。 请看下面我的代码的简化版本,它不工作。 当我调试这段代码时,我希望在TestMap4对象中有3项,但只有1项 List<String> lst = new ArrayList<>(); lst.add("Hello"); lst.add("World"); Map<List<String>, Integer> testMap4 = new HashMap<List<S

我尝试使用HashMap和HastTable,并将对象列表作为键。 请看下面我的代码的简化版本,它不工作。 当我调试这段代码时,我希望在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);
List lst=new ArrayList();
加上(“你好”);
第1条添加(“世界”);
Map testMap4=新的HashMap();
testMap4.put(lst,1);
testMap4.put(lst,2);
testMap4.put(lst,5);
当我将一个新项目放入HashMap对象时会发生什么?为什么不起作用

我在下面这个新例子中得到了相同的结果。(每个列表包含相同的2个字符串)

List lst=new ArrayList();
加上(“你好”);
第1条添加(“世界”);
List lst2=新的ArrayList();
lst2.添加(“你好”);
lst2.添加(“世界”);
List lst3=新的ArrayList();
lst3.添加(“你好”);
lst3.添加(“世界”);
Map testMap4=新的HashMap();
testMap4.put(lst,1);
testMap4.put(lst2,2);
testMap4.put(lst3,5);

如果我只修改2个字符串中的1个字符,这是正常的

它不起作用,因为您每次都使用同一个键来存储不同的值,因为所有值都映射到同一个键,而hashmap只存储最后一个值,因为该值覆盖了以前的值。

您不理解
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
其次,使用可变对象(一个
列表
)作为键,如果在将任何列表插入地图后对其进行修改,则会导致未定义的行为。只有当条目第一次插入到映射中时,才会根据
列表
(参见Javadoc)的契约计算哈希代码。列表内容的更改将更改哈希代码,您将无法再找到条目


使用
列表
(或任何可变对象)作为
HashMap
中的键是一个非常糟糕的主意™.

HashMap对放入HashMap中的键对象调用
hashCode()
方法

由于您没有为您使用的键类重写它(
List
,在您的例子中),它调用
java.lang.Object
上的
hashCode()
方法,该方法返回唯一的对象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()
equals()
。如果您只覆盖其中一个,您将立即死掉!!;)

您误解了映射的键/值部分:。映射只能有1个值,该值与1个唯一键关联。您使用相同的键放置这些值,因此每次覆盖现有值时,数字1、2和5的内容是什么?您是否试图将列表(相同列表)与键1、2和5相对应。如果您的键和值是错误的,那么有没有办法修改每个项列表的Hashcode以将其标识为唯一的?我已经扩展了ArrayList类并像这样重写了Hashcode()方法:
@Override public int Hashcode(){return UUID.randomUUID().Hashcode();}
这在我的情况下似乎是可行的。所以这绝对是错误的!!如果您返回一个随机数,那么
put(o,x)
上的hashCode将不同于
get(o)
上的hashCode,这意味着您将无法再次从HashMap中检索您的值!如果将一个字符串作为键放入映射中两次,则第二次put也将覆盖第一次put!这就是地图的工作原理!我研究了AbstractList的equals和compare,它们已经被实现为基于列表的内容给出一个hashCode和equals。因此,无需重写某些内容,除非您希望检索相同的值,无论您在将列表放入映射后如何修改列表。在这种情况下,我将覆盖hashCode并比较调用
Object
s equals并比较。
 HashMap<Integer,String> hm=new HashMap<Integer,String>();  
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);
static int java.util.Objects.hash(Object... values)
static boolean java.util.Arrays.equals(Object[] a, Object[] a2)