简体   繁体   English

为什么Collection接口有equals()和hashCode()?

[英]Why does the Collection interface have equals() and hashCode()?

为什么Collection接口有equals(Object o)hashCode() ,因为默认情况下任何实现都会有这些(继承自Object )?

From the Collection JavaDoc :集合 JavaDoc

While the Collection interface adds no stipulations to the general contract for the Object.equals , programmers who implement the Collection interface "directly" (in other words, create a class that is a Collection but is not a Set or a List ) must exercise care if they choose to override the Object.equals .虽然Collection接口没有对Object.equals的一般契约添加任何规定,但“直接”实现Collection接口的程序员(换句话说,创建一个是Collection但不是SetList )必须小心如果他们选择覆盖Object.equals It is not necessary to do so, and the simplest course of action is to rely on Object's implementation, but the implementor may wish to implement a "value comparison" in place of the default "reference comparison."没有必要这样做,最简单的做法是依赖 Object 的实现,但是实现者可能希望实现一个“值比较”来代替默认的“引用比较”。 (The List and Set interfaces mandate such value comparisons.) ListSet接口要求进行这样的值比较。)

The general contract for the Object.equals method states that equals must be symmetric (in other words, a.equals(b) if and only if b.equals(a) ). Object.equals方法的一般约定规定 equals 必须是对称的(换句话说, a.equals(b)当且仅当b.equals(a) )。 The contracts for List.equals and Set.equals state that lists are only equal to other lists, and sets to other sets. List.equalsSet.equals的契约声明列表仅等于其他列表,并设置为其他集合。 Thus, a custom equals method for a collection class that implements neither the List nor Set interface must return false when this collection is compared to any list or set.因此,当将此集合与任何列表或集合进行比较时,既不实现List也不实现Set接口的集合类的自定义 equals 方法必须返回 false。 (By the same logic, it is not possible to write a class that correctly implements both the Set and List interfaces.) (根据相同的逻辑,不可能编写一个正确实现 Set 和 List 接口的类。)

and

While the Collection interface adds no stipulations to the general contract for the Object.hashCode method, programmers should take note that any class that overrides the Object.equals method must also override the Object.hashCode method in order to satisfy the general contract for the Object.hashCode method.虽然 Collection 接口没有对Object.hashCode方法的通用约定添加任何规定,但程序员应该注意,任何重写Object.equals方法的类也必须重写Object.hashCode方法以满足Object.hashCode的通用约定Object.hashCode方法。 In particular, c1.equals(c2) implies that c1.hashCode()==c2.hashCode() .特别是, c1.equals(c2)意味着c1.hashCode()==c2.hashCode()

To answer your specific question: why does it have these methods?回答你的具体问题:为什么它有这些方法? It's done simply for convenience to be able to include Java Docs giving hints as to what implementers should do with these methods (eg comparing equality of values rather than references).这样做只是为了方便,能够包含 Java Docs,提供关于实现者应该用这些方法做什么的提示(例如比较值的相等性而不是引用)。

To add to the other great answers.添加到其他很棒的答案中。 In the Collections interface, the equals method is defined in that interface to make some decisions in the way equaling two instances of collection should work.在 Collections 接口中,equals 方法在该接口中定义,以做出一些决定,使集合的两个实例相等。 From the JAVA 8 documentation :来自JAVA 8 文档

More generally, implementations of the various Collections Framework interfaces are free to take advantage of the specified behavior of underlying Object methods wherever the implementor deems it appropriate.更一般地说,各种集合框架接口的实现可以自由地利用底层对象方法的指定行为,只要实现者认为合适。

So you don't add methods from the Object class for any other reason that giving more definitiveness to the java doc.因此,您不会出于任何其他原因而从 Object 类中添加方法,从而为 java 文档提供更多确定性。 This is the reason why you don't count those methods in the abstract methods in the abstract methods of an interface.这就是为什么你不在接口的抽象方法中计算抽象方法中的那些方法的原因。

Moreover, in JAVA 8, along the same line of reasoning, default methods from the Object class are not allowed and will generate a compile error.此外,在 JAVA 8 中,按照相同的推理思路,来自 Object 类的默认方法是不允许的,并且会产生编译错误。 I believe it's was done to prevent this type of confusion.我相信这样做是为了防止这种混淆。 So if you try to create a default method called hashCode(), for example, it will not compile.因此,例如,如果您尝试创建一个名为 hashCode() 的默认方法,它将无法编译。

Here is a more in-depth explanation for this behavior in JAVA 8 from the Lambda FAQ :以下是Lambda FAQ中对 JAVA 8 中这种行为的更深入的解释:

An interface cannot provide a default implementation for any of the methods of the Object class.接口不能为 Object 类的任何方法提供默认实现。 This is a consequence of the “class wins” rule for method resolution: a method found on the superclass chain always takes precedence over any default methods that appear in any superinterface.这是方法解析的“类获胜”规则的结果:在超类链上找到的方法总是优先于出现在任何超接口中的任何默认方法。 In particular, this means one cannot provide a default implementation for equals, hashCode, or toString from within an interface.特别是,这意味着不能在接口内为 equals、hashCode 或 toString 提供默认实现。

This seems odd at first, given that some interfaces actually define their equals behavior in documentation.考虑到某些接口实际上在文档中定义了它们的 equals 行为,这起初看起来很奇怪。 The List interface is an example. List 接口就是一个例子。 So, why not allow this?那么,为什么不允许这样做呢?

One reason is that it would become more difficult to reason about when a default method is invoked.一个原因是,何时调用默认方法会变得更加难以推理。 The current rules are simple: if a class implements a method, that always wins over a default implementation.当前的规则很简单:如果一个类实现了一个方法,那么它总是胜过默认实现。 Since all instances of interfaces are subclasses of Object, all instances of interfaces have non-default implementations of equals, hashCode, and toString already.由于接口的所有实例都是 Object 的子类,因此接口的所有实例都已经具有 equals、hashCode 和 toString 的非默认实现。 Therefore, a default version of these on an interface is always useless, and it may as well not compile.因此,接口上这些的默认版本总是无用的,它也可能无法编译。

Another reason is that providing default implementations of these methods in an interface is most likely misguided.另一个原因是在接口中提供这些方法的默认实现很可能是误导。 These methods perform computations over the object's state, but the interface, in general, has no access to state;这些方法对对象的状态执行计算,但接口通常无法访问状态; only the implementing class has access to this state.只有实现类可以访问此状态。 Therefore, the class itself should provide the implementations, and default methods are unlikely to be useful.因此,类本身应该提供实现,默认方法不太可能有用。

Just to add to the great answers above, it makes sense to have the 'equals' or `hashCode' methods in this scenario:只是为了添加上面的好答案,在这种情况下使用“equals”或“hashCode”方法是有意义的:

Collection<Whatever> list1 = getArrayList();
Collection<Whatever> list2 = getAnotherArrayList();

if(list1.equals(list2)){
    // do something
}

In the absence of the equals method in the interface, we'll be forced to use concrete types, which is generally not a good practice :如果接口中没有equals方法,我们将被迫使用具体类型,这通常不是一个好习惯:

ArrayList<Whatever> list1 = getArrayList();
ArrayList<Whatever> list2 = getAnotherArrayList();

if(list1.equals(list2)){
    // do something
}

Equals and hashCode method help to compare objects. Equals和hashCode方法有助于比较对象。 Collection interface works on different object in-order to compare them or in-order to check duplicates equals and hashcode will be used. 集合接口对不同对象按顺序进行比较,或者按顺序检查重复项是否相等,并将使用哈希码。

Equalable & Hashable are two default provided contracts/rules. Equalable&Hashable是两个默认提供的合同/规则。 By having this It's assumed that equals and hashCode for a given class are implemented correctly for that class. 通过这样做,假定为该类正确实现了给定类的equals和hashCode。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 不具有 equals 和 hashCode 的类型的集合 - Collection of a type that does not have equals and hashCode 接口中的 toString()、equals() 和 hashCode() - toString(), equals(), and hashCode() in an interface 如果存在hashCode(),为什么Java需要equals()? - Why does Java need equals() if there is hashCode()? 为什么 hashcode 和 equals 方法不适用于 ArrayList? - Why hashcode and equals method does not work with ArrayList? 为什么StringBuffer / StringBuilder不覆盖equals或hashCode? - Why does StringBuffer/StringBuilder not override equals or hashCode? 为什么不允许外部接口为HashMap提供hashCode / equals? - Why not allow an external interface to provide hashCode/equals for a HashMap? 为什么Entry接口定义了equals和hashCode等方法? - Why Entry interface defines methods like equals and hashCode? 为什么在会话外部的休眠实体要实现equals()和hashcode()? - Why Should Hibernate Entities outside of a Session have equals() and hashcode() implemented? 为什么 java 类 WeakReference 不会覆盖 hashcode 和 equals - why java class WeakReference does not override hashcode and equals 为什么Java EE 6需要为资源适配器实现equals()和hashCode()? - Why does Java EE 6 require equals() and hashCode() to be implemented for Resource Adapters?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM