在下面的代码中,如果参数为{1,3,2},则在while循环中,i为1,3,2。
我已经在使用LinkedHashSet,为什么订单不是1,2,3?我还需要做什么才能按升序进行迭代?
在o(log n)时间内无法使用TreeSet
add, remove, contains()
。
public static void iterate(int[] num) {
LinkedHashSet<Integer> set = new LinkedHashSet<Integer>();
for (int i : num) {
set.add(i);
}
Iterator<Integer> iter = set.iterator();
while (iter.hasNext()) {
// WHY IS i THE SAME ORDER AS INSERATION ORDER, NOT ASSENDING ORDER?
int i = iter.next();
}
}
答案 0 :(得分:5)
因为LinkedHashSet按插入顺序迭代而没有排序!来自javadoc:
此实现与HashSet的不同之处在于它维护了一个贯穿其所有条目的双向链表。此链接列表定义迭代排序,即元素插入集合(插入顺序)的顺序。
您将希望将TreeSet用于有序集,请查看有序集javadoc:https://docs.oracle.com/javase/7/docs/api/java/util/SortedSet.html
答案 1 :(得分:1)
所以你想要一个快速contains
的HashSet,并且正确地看到LinkedHashSet维护了一个额外的数据结构,不幸的是通过插入进行排序。
如果上面的代码显示所有插入,您可以提前对插入的数据进行排序:
Arrays.sort(num);
Collections.addAll(set, num);
更通用的解决方案是将集合复制到新集合中并对其进行排序。
如果数字在特定范围内,尤其是正数且不稀疏,则可以使用 BitSet 。如果适用的话,这确实是一个高效的解决方案。
答案 2 :(得分:1)
在返回迭代器之前,没有Java实现进行排序。只有像TreeSet
这样的实现由于其数据结构而被排序。
在某些时候必须进行分类。不能有(哈希)实现支持常量时间adding
和getting
并且具有固有的排序。如果这样的事情存在,那么我们就能够在恒定的时间内进行排序。
如果您想继续使用Hash
- 实施,那么您必须在检索元素之前/之后直接进行“排序工作”。由于您无法更改before
,唯一的解决方案是排序after
检索元素。
使用Guava的订购示例代码:
while (Integer i : Ordering.natural().sortedCopy(hashSet)) {
// "i" in sorted order
}