LinkedHashSet构造函数是否保留顺序?

6
构造函数LinkedHashSet(Collection<? extends E> c)是否保证其参数的顺序,假设该参数是有序集合?我们如何确定这一点?
Javadoc文档没有提到顺序:
构造一个新的链接哈希集合,其元素与指定集合相同。链接哈希集合是使用足以容纳指定集合中的元素和默认负载因子(0.75)的初始容量创建的。
我不认为它不会保留顺序,但我想知道它是否被保证(对于当前和未来的实现)。

1
JDoc -> 这个链表定义了迭代顺序,即元素插入集合的顺序(插入顺序)。请注意,如果将元素重新插入到集合中,则不会影响插入顺序。(如果在调用s.contains(e)返回true之前立即调用s.add(e),则元素e将被重新插入到集合s中。)基本上,它维护了插入顺序。这使您可以按照元素插入的顺序遍历集合。 - SedJ601
1
@SedrickJefferson 很好的发现。文档的那部分内容表明顺序将被保留。 - AnnTea
2个回答

5

查看Java 8版的java.util.LinkedHashSet实现,您可以看到以下构造函数:

public LinkedHashSet(Collection<? extends E> c) {
    super(Math.max(2*c.size(), 11), .75f, true);
    addAll(c);
}

那么addAll的内容是什么?

public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

addAll 方法通过对构造函数中使用的集合进行循环来实现:

for (E e : c)

这意味着,如果构造函数中使用的集合实现是有序的(例如java.util.TreeSet),那么新的LinkedHashSet实例的内容也将是有序的。
Java 9 中的实现非常相似。
是的,在传入的集合是有序的情况下,顺序会被保留。
只有通过检查特定情况下的实现,才能确定此点。

因为“只有通过检查特定情况下的实现,您才能确定这一点”,所以被接受。 - AnnTea

3

它通过内部使用addAll保留了集合迭代器返回的顺序:

遍历指定的集合,并依次将迭代器返回的每个对象添加到此集合中。


你是在暗示实现不能改变吗?有什么保证呢? - AnnTea
3
@AnnTea,技术上讲,没有任何保证。但考虑到 Java 拥有很强的向后兼容性,而且现有实现已经很完善,所以改变实现方式是非常不可能的。不过,按照规范创建自己的 JDK 并进行不同的实现是完全合法的。请注意,这并不改变原来的意思。 - Kayaman
@Kayaman 这可能是我正在寻找的答案(虽然不希望如此)。 - AnnTea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接