我使用HashSet
添加元素并检索它们,我知道我不会按顺序检索我添加它们的数据,但我想知道它发生的确切原因?
import java.util.HashSet;
import java.util.Iterator;
public class HS {
public static void main(String args[]) {
HashSet h=new HashSet();
h.add("Mayank");
h.add("Mayank");
h.add("Vashist");
h.add("Dinesh");
h.add("Vashist");
Iterator itr=h.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
答案 0 :(得分:9)
这只是来自javadoc
的java中Set
的合同
返回此set中元素的迭代器。 元素以无特定顺序返回(除非此集合是某个提供保证的类的实例)。因此,不需要
Set
的实现来维护值中的任何顺序。
为了按Set
需要维护订单的顺序返回值。这需要速度和空间成本。
LinkedHashSet
维护广告订单。
答案 1 :(得分:3)
HashSet不保留元素添加顺序。首先,它计算应该保持不变但很难预测的对象哈希码,然后使用它来选择一个桶,该桶是已选择相同桶的对象列表。由于Iterator
只是迭代所有桶,迭代顺序在很大程度上是不可预测的。
如果您需要保留订单,请使用LinkedHashSet。但是LinkedHashSet
维护了一个额外的链表,因此需要更多资源。
答案 2 :(得分:2)
因为在HashSet中存在为每个对象计算的哈希值,并且此哈希值确定容器中特定对象的数组索引。因此,插入元素的顺序自然不会被保留。 这允许访问具有O(1)复杂度的所需元素,但是它花费了大量内存。
答案 3 :(得分:1)
HashSet
使用所谓的hash table来存储项目。
哈希表由几个“插槽”组成,您的项目将放入其中。决定放置项目的插槽取决于该项目的散列码,该散列码通常与项目的自然顺序无关。
另一方面,TreeSet
根据项目的自然顺序存储项目,允许按顺序遍历其内容。此顺序将基于对象的自然顺序而不是它们的插入顺序。 TreeSet
和HashSet
之间的另一个区别是HashSet
提供O(1)查找,插入和删除,其中TreeSet
提供O(log(n))
查找,插入和删除。
LinkedHashSet通过在元素插入时构建链接来维护项目的插入顺序。
答案 4 :(得分:0)
来自官方文件:
此类实现Set接口,由哈希表支持 (实际上是一个HashMap实例)。它不能保证 集合的迭代顺序;特别是,它并不保证 订单将随着时间的推移保持不变。 [...]迭代器返回 通过这个类的迭代器方法是失败快速的:如果修改了集合 在创建迭代器之后的任何时候
答案 5 :(得分:0)
这是订购版本:
import java.util.Set;
import java.util.Iterator;
import java.util.Collections;
import java.util.LinkedHashSet;
public class HS {
public static void main(String args[]) {
Set<String> h=Collections.synchronizedSet(new LinkedHashSet<String>());
h.add("Mayank");
h.add("Mayank");
h.add("Vashist");
h.add("Dinesh");
h.add("Vashist");
Iterator<String> itr=h.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}