Java Theory and Practice: Hash Effective and Correct Definition Hashcode () and Equals () Level: Getting Started Brian Goetz Quiotix Corp Chief Consultant In August 2003 Each Java object has hashcode () and equals () methods. Many classes ignore the default implementation of these methods to provide a deeper semantic comparability between object instances. In the part of Java concept and practice, Java Developers Brian Goetz introduced you to rules and guidelines that should be followed by the Java class to effectively and accurately define havehcode () and equals (). You can explore your views on this article with the author and other readers in the discussion forum. (You can also click on the discussion of the top or bottom of this article to enter the forum.) Although the Java language does not directly support the associated array - can use any object as an indexed array - but use the hashcode () method in the root Object class clearly expressed expectations. Hashmap (and its senior hashtable) is widely used. Ideally based on haveh-based containers provide effective insertion and effective search; directly in the object mode to facilitate the development and use of a hash-based container. Define the object's equivalent Object class There are two ways to infer the identity of the object: equals (), and havehcode (). In general, if you ignore one of them, you must ignore these two because there must be a crucial relationship that must be maintained. Special circumstances are based on the equals () method, if the two objects are equal, they must have the same HashCode () value (although this is usually not true). The semantics of the specific class Equals () are defined on the left side of the Implementer; define what is equally equally equally, what is part of its design work. The default implementation of Object provides the following equation: Public Boolean Equals (Object Obj) {Return (this == Obj);} In this default implementation, only they reference the truly identical object, these two references It is equal. Similarly, the default implementation of HashCode () provided by Object is generated by incorporating the memory address of the object. Since some architectures, the address space is greater than the range of int values, two different objects have the same HashCode (). If you ignore HashCode (), you can still use the System.IdentityHashCode () method to access such default. Ignore Equals () - Simple instances By default, equals () and havehcode () are reasonable based on identification implementation, but for some classes, they wish to relax the definition of equation. For example, an Integer class definition equals () is similar to: public boolean equals (object obj) {return (Obj InstanceOf Integer && INTVALUE () == ((Integer) .intValue ());} In this definition, only The two Integer objects are equal in the case where the same integer value is included. Combined with Integer that will not be modified, this makes it possible to use Integer as the keyword in the HashMap is practical. This value-based Equal method can be used by all original package classes in the Java class library, such as Integer, Float, Character, and Boolean and String (if the two String objects contain the same order characters, then they are equal). Since these classes are unmodified and have havehCode () and equals (), they can be used as a good burst key.
Why ignore equals () and havehcode ()? If Integer does not ignore the equals () and havehcode () situation? If we have never used Integer as keywords in HashMap or other hash, what is not will happen. However, if we use such an Integer object as a keyword in HashMap, we will not be able to reliably retrieve relevant values unless we use an extremely similar Integer instance in the PUT () call in the GET () call. This requires that an instance of Integer objects corresponding to a particular integer value can be used in our entire program. Needless to say, this method is extremely inconvenient and error is frequent. Object's Interface Contract requires that if both equals () is equal, they must have the same HashCode () value. When its identification capacity is included in equals (), why do we need hashcode ()? Hashcode () method is purely used to improve efficiency. The Java platform designer is expected to have an importance of a list-based collection class in a typical Java application, such as HashTable, Hashmap, and HashSet, and use equals () to compare more objects in comparison. All Java objects can support HashCode () and combine with a hash-based collection that can be effectively stored. Implementing Equals () and HashCode () requirements Equals () and havehcode () have some restrictions, and these restrictions are raised in the Object file. Especially equals () methods must display the following properties: Symmetry: Two references, A and B, a.equals (b) if and only if b.equals (a) Reflexivity: All non-air references, a.equals (a) TRANSITIVITY: IF a.Equals (b) and b.equals (c), THEN A.Equals (c) Consistency with hashcode (): Two equal objects must have the same havehcode () value Object is not clear in the specification. Equals () and havehCode () must be consistent - their results will be the same in subsequent calls, assuming "" Does not change any information used in the syndrome comparison. "This sounds like" the results of the calculation will not Change, unless the actual situation is true. "This fuzzy declaration usually interprets the deterministic function of the object and has a hash value, not other. What does the object level mean? It is easy to meet the requirements of Equals () and Hashcode () of the Object class specification. Decide whether to neglect Equals (), except for judgment, it also requires other. In a simple unparalleled class, such as Integer (in fact, almost all unmodified classes), select quite obvious-equivalent should be based on the equivalent of the basic object state. In Integer case, the only state of the object is a basic integer value. For modified objects, the answer is not always so clear. Is Equals () and havehcode () should be based on object's identity (like default) or object status (icon integer and string)? There is no simple answer - it depends on the plan of the class. For containers such as List and Map, people argue. Most classes in the Java class library, including container classes, errors appear to provide Equals () and havehcode () implementation based on object status. If the HashCode () value of the object can be changed based on its status, we must pay attention when using such objects as a key based on the hash, make attention to ensure that when they are used as a hash keyword, we don't Allow changes to their status.
All hash-based collection assumptions that it does not change when the hash value of the object is used as a keyword in the collection. If its hash code is changed when the keyword is changed, some unpredictable and easily confusing results will be generated. This is usually not a problem during practice - we don't often use the modified object like List as a keyword in HashMap. An example of a simple modified class is Point, which defines Equals () and hashcode () based on status. If the two Point objects reference the same (x, y) coordinates, the POINT has a hash value from the IEEE 754-bit of the X and Y coated values, and they are equal. For complicated classes, equals () and havehcode () behavior may be even affected by SuperClass or Interface. For example, the List interface requires that if there is only another object being List, and they have the same order of Elements (Object.equals () defined by Element), the List object is equal to another object. Hashcode () needs more special -List's hashcode () value must meet the following calculations: hashcode = 1; item i = list.iterator (); while (I.hasNext ()) {Object Obj = i.next () Hashcode = 31 * hashcode (obj == null? 0: Obj.hashcode ());} Al only have a hash value depends on the content of the List, but also specifies a special algorithm that combines the hash values of each ELEMENT. (String class specifies a similar algorithm for calculating the String's hash value.) Writing your own equals () and hashcode () methods ignore the default equals () method is relatively simple, but if you don't violate the SymmeTry or transferability (Transitivity) Demand, ignore the negligible equals () method is extremely difficult. When ignoring Equals (), you should always include some Javadoc comments in equals () to help users who wish to extends your class. As a simple example, consider the following: Class a {final b Somenonnullfield; c someotherfield; int SomenonStateField;} How should we write the equals () method of this class? This method is suitable for many situations: public boolean equals (object other) {// NOT STRICTLY Necessary, but offs a good optimizationif (this == Other) Return True; if (! (@StanceOf a)) Return False; A Othera = (a) other; return (someNonNullField.equals (otherA.someNonNullField)) && ((someOtherField == null) otherA.someOtherField == null:? someOtherField.equals (otherA.someOtherField)));} now we define the equals () We must define HashCode () in a unified approach. One unified but not always effectively defines how hashcode () is as follows: public int hashcode () {return 0;} This method will generate a large number of entries and significantly reduce the performance of HashMaps, but it meets specifications.