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

时间:2015-12-12 13:40:40

标签: java list hash hashmap hashcode

我对java中的List的hashCode实现有疑问。

为了更好地理解,我将简单描述我的数据结构。 我从两个不同的数据库中读取图形信息并将其存储在抽象图形表示中。因此,我有两个HashMaps,每个数据库一个。该地图包含String作为键,GraphLayer对象作为值:HashMap<String, GraphLayer>。 GraphLayer对象有两个类型为PaperMetaDataConferenceSerieAndInstance的自定义成员。 PaperMetaData由原始String类型的一些成员和HashMap<Author, Set<Affiliation>>的成员组成。作者只包含原始的String成员以及Affiliation。 ConferenceSerieAndInstance还包含普通的String成员和类型为HashMap<String, ConferenceInstance>的成员,其中类ConferenceInstance只包含String成员。 我希望,到目前为止一切都很清楚。

我从每个数据库中读出我的信息,并将其存储在数据库的每个HashMap中。然后我转换列表中的每个地图。到目前为止一切顺利,但列表中对象的顺序是不同的(以及在我转换地图之前的地图中)。从HashMap到ArrayList的转换看起来像这样。

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

但两个列表都包含相同的对象。如果我调用每个列表的方法hashCode(),我会得到不同的哈希码。

我不明白为什么我会得到不同的哈希码。根据java文档,列表的哈希码将被创建。

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

因此列表中项目的顺序不应起作用。如果我尝试使用具有原始数据类型的列表(如String),它将起作用,但不能使用我的自定义数据类型。

有没有人知道它为什么不起作用?

我还比较了列表1中PaperMetaDataConferenceSerieAndInstance成员的每个哈希码,以及列表2中成员的哈希码。而且没有区别。但是如果我比较完整列表的哈希码,就会有所不同。我不知道为什么。我无助。

也许有人可以帮助我。最好的问候和提前感谢。

1 个答案:

答案 0 :(得分:3)

你的答案就在这里

  

到目前为止一切顺利,但列表中对象的顺序是不同的   (以及在转换地图之前的地图中)。

List#equals()

  

[...]如果两个列表包含相同的元素,则它们被定义为相等   相同的订单

编辑@SamiKuhmonen

详细说明:哈希码计算有一个求和和乘法的循环。如果哈希码是1和2以及另一个列表2和1,则结果是1 * 31 + 2和2 * 31 + 1,因此很明显它们不相同。

实施例

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