Java LinkedHashSet.equals()与LinkedList.equals()具有相同元素但顺序不同

Java LinkedHashSet.equals()与LinkedList.equals()具有相同元素但顺序不同,java,collections,linked-list,equals,linkedhashset,Java,Collections,Linked List,Equals,Linkedhashset,考虑以下SSCCE: public static void main(String[] args) { LinkedHashSet<String> set1 = new LinkedHashSet<>(); set1.add("Bob"); set1.add("Tom"); set1.add("Sam"); LinkedHashSet<String> set2 = new LinkedHashSet<>();

考虑以下SSCCE:

public static void main(String[] args) {
    LinkedHashSet<String> set1 = new LinkedHashSet<>();
    set1.add("Bob");
    set1.add("Tom");
    set1.add("Sam");
    LinkedHashSet<String> set2 = new LinkedHashSet<>();
    set2.add("Sam");
    set2.add("Bob");
    set2.add("Tom");

    System.out.println(set1);
    System.out.println(set2);
    System.out.println(set1.equals(set2));
}
但是如果您将
LinkedHashSet
更改为
LinkedList

public static void main(String[] args) {
    LinkedList<String> set1 = new LinkedList<>();
    set1.add("Bob");
    set1.add("Tom");
    set1.add("Sam");
    LinkedList<String> set2 = new LinkedList<>();
    set2.add("Sam");
    set2.add("Bob");
    set2.add("Tom");

    System.out.println(set1);
    System.out.println(set2);
    System.out.println(set1.equals(set2));
}
我的问题是澄清。有人能解释一下吗?为什么一个
LinkedHashSet
会被认为是相等的,而同样的
LinkedList
却不会?我假设
List
Set
的定义起作用,但我不确定


基本上,我是说如果你认为<代码>设置<代码> s是相同的,你不认为<代码>列表< /代码> s也一样吗?反之亦然(假设没有重复的元素)

LinkedHashSet的保证是关于迭代顺序的。然而,它仍然是一个
集合
,集合本身并不关心顺序。另一方面,
列表
。元素位于第3位的
列表
与元素位于第1位的另一个
列表
不同

为方法设置
javadoc

如果指定的对象也是一个集合,则返回true,这两个集合具有 相同的大小,并且指定集合的每个成员都包含在 此集合(或等效地,此集合的每个成员都包含在 指定的集合)此定义确保equals方法 在set接口的不同实现中正常工作。

LinkedHashSet
javadoc状态

哈希表和链表的集合接口的实现,用 可预测的迭代顺序

LinkedHashSet
是一个
集合
。它具有相同的规则,即适用于集合ADT的规则。

如上所述: LinkedHashSet扩展了HashSet,HashSet扩展了AbstractSet,AbstractSet实现了equals方法:

将指定对象与此集合进行相等性比较。如果给定对象也是一个集合,两个集合的大小相同,并且给定集合的每个成员都包含在此集合中,则返回true。这确保equals方法在Set接口的不同实现中正常工作

如果顺序对您很重要,比较LinkedHashSet的最简单方法是序列化并比较它们:

    LinkedHashSet<Integer> reverseOrder = new LinkedHashSet<>();
    reverseOrder.add(2);
    reverseOrder.add(1);
    LinkedHashSet<Integer> ordered = new LinkedHashSet<>();
    ordered.add(1);
    ordered.add(2);
    System.out.println("Equals via set: " + ordered.equals(reverseOrder));
    System.out.println("Equals With Arrays: " + ordered.ordered.toString().equals(reverseOrder.ordered.toString()));

但是
LinkedHashSet
确实关心顺序,所以它不应该有自己的
.equals()
方法来确定顺序相等吗?@ryvantage顺序只用于迭代,而不是
集所代表的内容。而且,它没有自己的
equals
方法。它继承了
抽象集
。我想我的问题更多的是一个为什么的问题。“此定义确保equals方法在set接口的不同实现中正常工作。”这一部分确实有所帮助。
Set
的每个实现必须具有相同的标准。虽然我仍然不知道为什么,但很明显,LHS只是遵循了
集合
平等定义中设定的标准。在我看来,两个具有不同顺序的
LinkedHashSet
s并不相等,这似乎仍然是合乎逻辑的。我是唯一的一个吗?@ryvantage这些类是用来实现的。集合就是这样一种数据结构。它被定义为
一种抽象数据结构,可以存储特定的值,没有任何特定的顺序,也没有重复的值。
换句话说,顺序对集合并不重要。
LinkedHashSet
中的顺序只对程序员很重要,但不会影响集合数据结构的定义。@ryvantage从另一个角度看它。如果您依赖于一个具有返回
Set
的API的库,并且您将该库的某些修补程序应用于您的应用程序,这些修补程序应该是内部错误修复程序,并且您的应用程序会崩溃和烧毁,因为开发人员出于内部原因在后台更改了实现。。。你觉得这合乎逻辑吗?:)
toArray
方法返回一个新数组,对于数组,
equal
方法检查引用相等性-因此代码片段没有真正意义(即,即使两个集合中的顺序相同,第二个输出仍然是
false
…)这是一个很好的观点,更改为序列化两个列表,然后进行比较。
[Bob, Tom, Sam]
[Sam, Bob, Tom]
false
    LinkedHashSet<Integer> reverseOrder = new LinkedHashSet<>();
    reverseOrder.add(2);
    reverseOrder.add(1);
    LinkedHashSet<Integer> ordered = new LinkedHashSet<>();
    ordered.add(1);
    ordered.add(2);
    System.out.println("Equals via set: " + ordered.equals(reverseOrder));
    System.out.println("Equals With Arrays: " + ordered.ordered.toString().equals(reverseOrder.ordered.toString()));
Equals via Set: true
Equals With Arrays: false