简体   繁体   English

搜索算法如何与Java集合中的对象(例如HashSet)一起使用?

[英]How does the search algorithm work with objects in a java collection such as HashSet?

The question really is regarding objects that change dynamically in a collection. 问题实际上是关于集合中动态变化的对象的。 Does the "contains" method go and compare each of the object individually every time or does it do something clever? 是“包含”方法每次都去比较每个对象,还是做得很聪明?

If you have 10000 entries in a collection, I would have expected it to work a bit more cleverly but not sure. 如果集合中有10000个条目,我希望它能更巧妙地工作,但不确定。 Or if not is there a way to optimise it by adding a hook that would tell the collection object to update hashcodes for the objects that have changed?? 或者如果没有,可以通过添加一个挂钩来优化它,该挂钩将告诉收集对象更新已更改对象的哈希码?

Additional Question: 附加问题:

Thanks for answers below... Can I also ask what happens in case of ArrayList? 感谢您提供以下答案...我还能问一下ArrayList会发生什么情况吗? I could not find anything in the documentation that says not to put mutable objects in ArrayList. 我在文档中找不到任何不要将可变对象放入ArrayList的内容。 Does that mean the search algorithm simply goes and compares against hashcode of each object?? 这是否意味着搜索算法会简单地将其与每个对象的哈希码进行比较?

They hash the object and look it up by its hash code. 他们对对象进行哈希处理并通过其哈希码进行查找。 If it is there, it will compare the objects themselves. 如果存在,它将比较对象本身。 This is because two or more objects that have the same hash might not be the same object. 这是因为具有相同散列的两个或更多对象可能不是同一对象。

Since Java's hash collections use buckets (chaining), they have to look at all the objects in the bucket. 由于Java的哈希集合使用存储桶(链接),因此它们必须查看存储桶中的所有对象。 These objects are kept in a linked list (not java.util.LinkedList , but a custom list) 这些对象保存在链接列表中(不是java.util.LinkedList ,而是自定义列表)

This is generally very efficient, and the HashSet.contains() method is amortized O(1) (constant time). 通常这非常有效,并且HashSet.contains()方法摊销 O(1)(恒定时间)。


Java's docs have an answer to the second part of your question: Java文档对问题的第二部分有一个答案:

Note: Great care must be exercised if mutable objects are used as set elements. 注意:如果将可变对象用作集合元素,则必须格外小心。 The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set. 如果对象的值更改为影响相等比较的方式,而该对象是集合中的元素, 则不指定集合的​​行为 A special case of this prohibition is that it is not permissible for a set to contain itself as an element. 此禁止的一种特殊情况是,不允许集合将自身包含为元素。

A HashSet computes the hash code of an element when it's added to the set. 当元素添加到集合中时, HashSet计算该元素的哈希码 It stores this in a way which makes it very efficient to find all elements with the same hash code. 它以一种非常有效的方式来存储所有具有相同哈希码的元素。

Then when you call contains() , it simply has to compute the hash code of the value you're looking for, and find all elements in the set with the same hash code. 然后,当您调用contains() ,它只需要计算您要查找的值的哈希码,并使用相同的哈希码查找集合中的所有元素。 There may be multiple elements as hash codes aren't unique, but there are likely to be far fewer elements with matching hash codes than there are elements within the set itself. 可能存在多个元素,因为哈希码不是唯一的,但是具有匹配哈希码的元素可能要比集合本身中的元素少得多。 Each matching element is then checked with equals until either a match is found or we've run out of candidates. 然后,对每个匹配元素进行equals检查,直到找到匹配项或候选用尽为止。

EDIT: To answer the second part, which somehow I'd missed on first reading, you won't be able to find the element again. 编辑:要回答第二部分,我一读就以某种方式错过了它,您将无法再次找到该元素。 You mustn't change an element used as a key in a hash table or an element in a hash set in any equality-affecting manner, or you will basically break things. 不得以任何影响平等的方式更改哈希表中用作键的元素或哈希集中的元素,否则,您基本上会破坏事情。

The simple answer is — no, nothing clever happens. 简单的答案是-不,没有聪明的事情发生。 If you expect an object's state to change in a way that affects its hashCode() and equals(...) behavior, then you must not store it in a HashSet , nor any other Set . 如果您希望对象的状态发生变化,从而影响其hashCode()equals(...)行为,则不得将其存储在HashSet或任何其他Set To quote from http://download.oracle.com/javase/6/docs/api/java/util/Set.html : 要引用http://download.oracle.com/javase/6/docs/api/java/util/Set.html

Note: Great care must be exercised if mutable objects are used as set elements. 注意:如果将可变对象用作集合元素,则必须格外小心。 The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set. 如果对象的值更改为影响equals比较的方式,而该对象是集合中的元素,则不指定集合的​​行为。 A special case of this prohibition is that it is not permissible for a set to contain itself as an element. 此禁止的一种特殊情况是,不允许集合将自身包含为元素。

A HashSet uses a HashMap under the hood. HashSetHashSet使用HashMap Therefore, the contains operation uses the hashCode() method in the object to check if it's present in the hash table implemented by HashMap . 因此, contains操作使用对象中的hashCode()方法检查其是否存在于HashMap实现的哈希表中。

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

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