1. Do custom objects have to override hashCode() and equals() methods

It isn’t. All Java objects inherit Object objects by default. Obejtc objects have hashCode() and equals(), but the default hashCode() method returns memory addresses. The default equals() compares the memory addresses of two objects, i.e. whether they are the same object. If the default method works for you, or if you don’t need either method at all, don’t rewrite it, just remember to rewrite it again the next time you use it… That’s why the specification makes you rewrite.

2. Do I have to override hashCode() if I override equals()

It isn’t. The most common use of these two methods is in a HashMap. Let’s look at what happens when a HashMap uses an Object as its key to put.

static final int hash(Object key) {
    int h;
    return (key == null)?0 : (h = key.hashCode()) ^ (h >>> 16);
}
Copy the code

The result of xor on the high and low 16 bits of the key’s hashCode() value is used as the hash value to determine the index subscript of the object in the Entry array of the HashMap. Suppose you have an existing TestObject,

public class TestObject {
    String name;
    String description;

    public TestObject(String name) {
        this.name = name;
    }

	@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null|| getClass() ! = o.getClass())return false;
        TestObject that = (TestObject) o;
        returnObjects.equals(name, that.name); }}Copy the code

Override equals() to treat TestObject as name, regardless of description property. We execute the following method:

public static void main(String[] args) {
    TestObject one = new TestObject("aaa");
    TestObject two = new TestObject("aaa");
    HashMap<TestObject, Integer> map = new HashMap<>();
    map.put(one, 1);
    map.put(two, 2);
    System.out.println(one.equals(two));
    System.out.println(map.size());
}
Copy the code

Output:

true
2
Copy the code

The HashMap determines the hashcode of the key. The HashMap determines the hashcode of the key. The HashMap determines the hashcode of the key and equals the same subscript position of the Entry array. Determines whether the same key overwrites or different keys form a linked list. I don’t have to, but I think you can conclude by looking at this that it’s probably best to rewrite it.

3. Do I have to override equals() if I overwrite hashCode()

The answer, really, is no. However, if the hashcode is not rewritten properly, it may result in the same hashcode values for a large number of different objects. As a result, when the hashMap is added, a large number of Entry positions in the array will be empty, and some positions will be very long linked lists. There are many online explanations), very bad.

4. Why not use an array as a HashMap key

Finally back to the problem. Because the array is not our custom object, and the array’s hashCode() method returns the memory address. Suppose we expect a HashMap to deduplicate or count the same number of arrays, we run into the problem in 2 where the same array has different keys.

5. What other requirements do HashMap keys have? (Interview questions)

In addition to the points above, it is important to note that the keys of a HashMap are ideally immutable objects. Using the TestObject example above, suppose you overwrite the hashCode and equalis methods:

public class TestObject {
    String name;
    String description;

    public TestObject(String name) {
        this.name = name;
    }

    @Override
    public int hashCode(a) {
        return Objects.hash(name);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null|| getClass() ! = o.getClass())return false;
        TestObject that = (TestObject) o;
        returnObjects.equals(name, that.name); }}Copy the code

Execute the following code:

public static void main(String[] args) {
    TestObject one = new TestObject("aaa");
    HashMap<TestObject, Integer> map = new HashMap<>();
    map.put(one, 1);
    System.out.println(map.get(one));
    one.setName("bbb"); 
    System.out.println(map.get(new TestObject("aaa")));
    System.out.println(map.get(new TestObject("bbb")));
    System.out.println(map.get(one));
}
Copy the code

Output:

1
null
null
null
Copy the code

The testObjects stored in the HashMap have been changed, but their positions in the Enry array have not changed. In this case, neither the original object, the modified object, the newly created AAA object, nor the newly created BBB object can find the 1 stored in the HashMap. The most commonly used String is used as a HashMap key because it is an immutable object.