Author: Code Pianist

Link: https://www.cnblogs.com/lulipro

preface

In programming, there are a lot of “conventions”. Adhering to conventions to implement your code will get you out of a lot of holes.

The Object class is the ancestor of all classes in Java, and equals and hashCode are two very important methods.

These two methods are always discussed together. Recently I was looking at the collection framework and decided to clean up some details in order to lay a foundation. Once and for all!

Let’s begin the analysis.

public boolean equals(Object obj)Copy the code

The default implementation in Object is: return this == obj. That is, this will return true only if this and obj refer to the same object.

Instead of checking their uniqueness, we use equals to determine whether two objects are equivalent. So when we implement our own class, we have to override equals.

By convention, equals satisfies the following rules:

  1. Reflexivity: x.equals(x) must be true

  2. For NULL: x. als(null) must be false

  3. Symmetry: x.equals(y) and Y. equals(x) have the same results

  4. Transitivity: A and B equals, b and C equals, then A and C must also be equal.

  5. Consistency: A change in the state of two objects during a run time does not affect the equals decision result, so no matter how many times equals is called during the run time, the same result is returned.

A case in point

class Test{ private int num; private String data; public boolean equals(Object obj) { if (this == obj) return true; if ((obj == null) || (obj.getClass() ! = this.getClass())) return false; // obj and this are identical and not null. Test test = (Test) obj; return num == test.num&& (data == test.data || (data ! = null && data.equals(test.data))); } public int hashCode() {// Override equals, which must also override hashCode. Details will be introduced later. }}Copy the code

Equals Writing Guide

The Test object has two fields, num and data. These two fields represent the status of the object and are also used to evaluate equals.

In line 8, the reference to the comparison passed in is compared to this. This is done to save execution time. If this and obj are references to the same heap object, then they must be qeuals.

If obj is null, then it must not be equals, because this must not be null since it can call equals.

Then, the runtime classes of the two objects are compared to see if they are the same class. If it is not the same class, it does not equals. GetClass returns a reference to the runtime classes of this and obj. If they belong to the same class, a reference to the same runtime class is returned. Note that a class is also an object.

1. Some programmers use the second way below instead of the first way to compare runtime classes. This should be avoided.

if((obj == null) || (obj.getClass() ! = this.getClass())) return false; if(! (obj instanceof Test)) return false; // avoid!Copy the code

It violates the principle of symmetry in the Convention.

For example, suppose Dog extends the Aminal class.

Dog Instanceof Animal gets true

Animal Instanceof Dog gets false

That would lead to

Animal. Equls (dog) returns true

T equals (animal) returns false

This is only guaranteed to be true if the Test class has no subclasses.

Equals can only compare objects of the same class. Different classes are always false. But it’s not mandatory. We also rarely need to use equals between different classes.

3. When comparing fields of objects, you can call equals for primitive values (note that floating point comparisons are a pit). You can also call equals for reference values, but you also need to handle null cases. For floating-point comparison, I found the following tips for floating-point comparison when I looked at the source code of Arrays. BinarySearch:

If (doubleToLongBits(d1) == doubleToLongBits(d2)) //d1 and d2 are Double types if(float.floatToIntBits (f1) == Float.floatToIntBits(f2)) // F1 and f2 are Float typesCopy the code

It is not always necessary to count all the fields of an object as equals, depending on your business requirements. For example, if you want to make a home appliance power statistics system, if the power of two home appliances is the same, there is enough basis to think that the two home appliance objects are equivalent, at least in your business logic background is equivalent, do not care about their price ah, brand ah, size and other parameters.

5. Finally, note that the equals method is of type Object.

public int hashCode()

This method returns the hash code of the object. The return value is a hash code of type int.

Object hash code is designed to better support hash-based Java collection classes such as Hashtable, HashMap, HashSet, etc.

The consistent convention for hashCode methods is:

  1. Objects overriding the euqls method must also override the hashCode() method.

  2. If two objects return true via equals, then the hashCode method of the two objects must return the same hashCode of type int

  3. If two objects return false through equals, their hashCode is allowed to return the same value. (programmers must be aware, however, that hashCode returns a unique hashCode that makes the hashtables that store this object work better.)

In the above example, the Test object has two fields, num and data. These two fields represent the state of the object and are also used to evaluate equals. So, in the hashCode method, these two fields also participate in the hash value, as intermediate arguments in the hash operation. This is crucial in order to follow the rule that hashCode must be the same if two objects are equals.

The fields that participate in equals must also participate in the hashCode calculation.

It stands to reason that different objects in the same class return different hash codes. The typical approach is to convert an object’s hash code based on its address, but this approach is not the only required implementation for Java. It’s usually not the best way to do it.

Compared to the equals recognized implementation convention, hashCode’s convention requirements are easy to understand. There are two key points that a hashCode method must follow. The third point of the convention, which is actually a refinement of the second point, is to look at the convention requirements for hashCode methods.

First: the same hashCode must be returned no matter how many times hashCode is called during a run time, as long as the object’s (field) changes do not affect the equals method’s decision result.

Second: The hashCode of the two objects that return true via equals calls must be the same.

Third: The hash codes of two objects that return false by equasl need not be different, that is, the return values of their hashCode methods are allowed to be the same.

To sum up: Equivalent (calling equals returns true) objects must produce the same hash code. Objects that are not equivalent do not require different hash codes to be generated.

HashCode writing guide

When writing hashCode, you need to consider that the final hash is an int and cannot overflow. The hash codes of different objects should be different to avoid hash conflicts.

So how do you do that? Here’s the solution.

1. Define a hash variable of type int, initialized to 7.

The next step is to hash the fields you consider important (equals). Each important field will generate a hash component that will contribute to the final hash value.

And then you add up all of the components, you don’t just add them up. Choose a multiple of the number 31 and participate in the calculation. It then recurses until all the fields are involved.

int hash = 7; Hash = 31 * hash + field 1 contribution; Hash = 31 * hash + field 2 contribution; . Return the hash.Copy the code

Note: I found and translated the following content on Google. I added my own words and some examples to make it easier to understand, but I can guarantee that it does not affect the overall accuracy.

English text: http://www.javaranch.com/journal/2002/10/equalhash.html

Click on the picture to join the Spring communication Group

Left left left

Have you learned anything after reading this article? Please share it with more people