简体   繁体   English

同一对象的两个列表具有不同的哈希码

[英]Two lists of same objects have different hash codes

I have a question regarding the hashCode implementation of an List in java. 我有一个关于Java中List的hashCode实现的问题。

For better understanding, I will simply describe my data construct. 为了更好地理解,我将仅描述我的数据构造。 I read graph information from two different databases and store it in a abstract graph representation. 我从两个不同的数据库中读取图形信息,并将其存储在抽象图形表示形式中。 Therefore I have two HashMaps, one for each database. 因此,我有两个HashMap,每个数据库一个。 The map contains a String as Key and a GraphLayer object as value: HashMap<String, GraphLayer> . 该映射包含一个String作为键,一个GraphLayer对象作为值: HashMap<String, GraphLayer> The GraphLayer object has two custom members of type PaperMetaData and ConferenceSerieAndInstance . GraphLayer对象具有两个类型为PaperMetaDataConferenceSerieAndInstance自定义成员。 PaperMetaData consists of some members of primitive String type and an member of HashMap<Author, Set<Affiliation>> . PaperMetaData由一些基本String类型的成员和HashMap<Author, Set<Affiliation>> The Author contains just primitive String members, as well as Affiliation. 作者仅包含原始String成员以及关联。 ConferenceSerieAndInstance contains also normal String members and a member of type HashMap<String, ConferenceInstance> , where the class ConferenceInstance just conatins String members. ConferenceSerieAndInstance还包含普通的String成员和HashMap<String, ConferenceInstance>类型的成员,其中ConferenceConference类仅包含String成员。 I hope, so far everything is clear. 我希望到目前为止,一切都还清楚。

I read out my information from each database and store it in each HashMap for the database. 我从每个数据库中读取我的信息,并将其存储在该数据库的每个HashMap中。 Afterwards I convert each map in a list. 之后,我将每个地图转换为列表。 So far so good, but the order of the objects in the list is different (as well as in the Map before I convert the map). 到目前为止,一切都很好,但是列表中对象的顺序是不同的(以及在转换地图之前,在地图中)。 The cast from HashMap to ArrayList looks like this. 从HashMap到ArrayList的转换看起来像这样。

public List<GraphLayer> searchAuthor() { 
    ...
    return (List<GraphLayer>) new ArrayList<GraphLayer>(graph.values());
}

But both lists contains the same objects. 但是两个列表都包含相同的对象。 If I call the Method hashCode() of each list, I get different hash codes. 如果我调用每个列表的方法hashCode()hashCode()得到不同的哈希码。

I don't understand why I get different hash codes. 我不明白为什么会得到不同的哈希码。 According to the java documentation, the hash code of a list will be created like that. 根据Java文档,将像这样创建列表的哈希码。

  int hashCode = 1;
  for (E e : list)
      hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

So the order of the items in the list should not play a role. 因此,列表中项目的顺序不起作用。 If I try it with a list with primitive datatypes, like String, it will work, but not with my custom datatype. 如果我尝试使用具有原始数据类型(如String)的列表进行操作,则它将起作用,但不适用于我的自定义数据类型。

Does anyone has an idea why it does not work? 有谁知道为什么它不起作用?

I compared also each hash code of the members of the PaperMetaData and ConferenceSerieAndInstance in list one, with the hash code of the members in list two. 我还比较了列表一中PaperMetaDataConferenceSerieAndInstance成员的每个哈希码,与列表二中的成员的哈希码。 And there is no difference. 而且没有区别。 But if I compare the hashcode of the complete list, there is a difference. 但是,如果我比较完整列表的哈希码,会有区别。 I have no idea why. 我不知道为什么。 I'm helpless. 我很无奈。

Perhaps somebody can help me out. 也许有人可以帮助我。 Best regards and thanks in advance. 最好的问候和预先的感谢。

Your answer lays here 你的答案就在这里

So far so good, but the order of the objects in the list is different (as well as in the Map before I convert the map). 到目前为止,一切都很好,但是列表中对象的顺序是不同的(以及在转换地图之前,在地图中)。

List#equals()

[...] two lists are defined to be equal if they contain the same elements in the same order [...]如果两个列表包含相同顺序的相同元素,则定义为相等


EDIT By @SamiKuhmonen 由@SamiKuhmonen编辑

And to elaborate: the hashcode calculation has a loop with summing and multiplying. 并且要详细说明:哈希码计算具有一个求和与乘法的循环。 If hashcodes are 1 and 2 and on another list 2 and 1, the results are 1*31+2 and 2*31+1, so it's clear that they are not the same. 如果哈希码是1和2,并且在另一个列表2和1上,则结果是1 * 31 + 2和2 * 31 + 1,因此很明显它们是不同的。


Example

List<String> one = new ArrayList<String>();
List<String> two = new ArrayList<String>();
List<String> three = new ArrayList<String>();
String[] s = "A B C".split(" ");

for (String a : s){
    one.add(a);
    two.add(a);
}

for (int i = s.length-1 ; i >= 0 ; i--){
    three.add(s[i]);
}

System.out.println(one.hashCode());     // 94369
System.out.println(two.hashCode());     // 94369
System.out.println(three.hashCode());   // 96289
System.out.println(one.equals(two));    // true
System.out.println(two.equals(three));  // false

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM