LinkedHashSet迭代不按升序排列?

时间:2014-11-13 13:44:36

标签: java data-structures collections linkedhashset

在下面的代码中,如果参数为{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();
    }
}

3 个答案:

答案 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这样的实现由于其数据结构而被排序。

在某些时候必须进行分类。不能有(哈希)实现支持常量时间addinggetting并且具有固有的排序。如果这样的事情存在,那么我们就能够在恒定的时间内进行排序。

如果您想继续使用Hash - 实施,那么您必须在检索元素之前/之后直接进行“排序工作”。由于您无法更改before,唯一的解决方案是排序after检索元素。

使用Guava的订购示例代码:

while (Integer i : Ordering.natural().sortedCopy(hashSet)) {
    // "i" in sorted order
}