简体   繁体   English

hashSet如何接纳元素

[英]How does a hashSet admit elements

I have a list of objects that I need to add to a HashSet, say List<Node> books . 我有一个需要添加到HashSet的对象列表,例如List<Node> books Say further that no two books are equal in the very sense that their equals method would each return false; 进一步说,就其equals方法将各自返回false的意义而言,没有两本书相等。 say, however, that their hashCode method each return 1 . 说,然而,他们的hashCode方法每个返回1 I am using this extreme case so that I can understand fully how admission works. 我正在使用这种极端情况,以便我可以完全理解录取的工作原理。 So my question is this: Will the HashSet admit all my objects? 所以我的问题是:HashSet会接受我所有的对象吗?

public class Book{
  ...
  @Override
  public boolean equals(Book other){
    return false;
  }

  @Override
  public int hashCode(){
    return 1;
  }
} 

recall that hashSet does not admit duplicates. 回想一下hashSet不允许重复。

I am wondering about this because by the very name a hashSet uses a hash of the object. 我对此感到疑惑,因为顾名思义,hashSet使用对象的哈希值。 Is that hash by any chance related to the hashCode of the object being added? 该哈希是否与要添加的对象的hashCode有关?

And yes I am aware of 是的,我知道

Adds the specified element to this set if it is not already present. 如果指定的元素尚不存在,则将其添加到该集合中。 More formally, adds the specified element e to this set if this set contains no element e2 such that (e==null ? e2==null : e.equals(e2)). 更正式地说,如果此元素集中不包含任何元素e2,则将指定元素e添加到该元素集合中,从而使(e == null?e2 == null:e.equals(e2))。 If this set already contains the element, the call leaves the set unchanged and returns false. 如果此集合已经包含该元素,则调用将使该集合保持不变并返回false。

But how are the hashCode of the object related to its hash value in the HashSet? 但是对象的hashCode与HashSet中的哈希值如何相关?

A Set is composed of buckets to speed up searching. 一个Set由多个组成,以加快搜索速度。 When new object is added to a Set , its hash is evaluated using object's hashCode() method. 将新对象添加到Set ,将使用对象的hashCode()方法评估其哈希值。

Then, based on that hash , the Set decides which bucket the object is to be stored in. 然后,根据该哈希Set决定将对象存储在哪个存储桶中。

Then, when you search for an object inside that Set (using for example contains() method), the hash is evaluated again, and then the Set iterates over all the elements in a single bucket (instead of iterating over all elements of a Set ). 然后,当您在该Set搜索对象时(例如,使用contains()方法),将再次对哈希进行求值,然后Set遍历单个存储桶中的所有元素(而不是遍历Set所有元素) )。 This makes it much faster, because - usually - set elements are distributed (more or less) equally among many buckets. 这使速度快得多,因为-通常-设置元素在多个存储桶之间平均分配(或多或少)。

In your case, all the objects will be stored in a single bucket, thus your Set will not really work differently (performance-wise, that is) than a List . 在您的情况下,所有对象都将存储在一个存储桶中,因此您的Set工作原理(就性能而言)实际上不会与List有所不同。

And answering the original question: Yes, it will store all your objects as long, as their equals() is implemented correctly. 并回答原始问题:是的,只要正确地实现了它们的equals() ,它将存储所有对象。

Use this answer: How does a Java HashMap handle different objects with the same hash code? 使用以下答案: Java HashMap如何处理具有相同哈希码的不同对象? and the information, that HashSet<E> is just a HashMap<E, Object> . 以及HashSet<E>只是HashMap<E, Object>

I'm slightly confused by your question. 你的问题让我有些困惑。 The HashSet will use the hashCode() method of the element you add (the List<Node> books in this case). HashSet将使用添加元素的hashCode()方法(在本例中为List<Node> books )。 So if you add the List itself, HashSet will call hashCode on the List , not on Book , unless you add the Book elements individually. 因此,如果您添加List本身,则HashSet将在List而不是Book上调用hashCode,除非您分别添加Book元素。 If you add them individually, it was call the hashCode() you defined in your question. 如果单独添加它们,则将其称为您在问题中定义的hashCode()

As a side note, don't ever return a constant value in your hashCode() . 附带说明,永远不要在hashCode()返回常量值。 See Best implementation for hashCode method 请参见hashCode方法的最佳实现

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

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