[Note] Java: Is it necessary to override equals for equality judgment?

Introduction

As mentioned in the Previous article, the current reference book (Introduction to Java that can be clearly understood / dp / B00O0NIW30 / ref = dp-kindle-redirect? _ Encoding = UTF8 & btkr = 1)) I am re-studying Java. (Actually, I have already read it: blush :)

In the above reference book, when creating a class, it is cautioned not to override the already provided method and cause an unintended problem. One example is the ʻequals` method.

The ʻequals method is a method that determines whether they are equivalent rather than equal. However, according to the reference book, the ʻequals method of the Object class that is originally provided determines whether it is equivalent or not by whether it is equal or not. So if the object that called ʻequals and the object passed as an argument to equals are equal, then the two objects are equivalent, right? It is a translation that judges the obvious thing as `.

Implementation

See the code below to support the above decision method: sunglasses: After creating an instance of the Person class, add it to ʻArrayList` and specify the deletion target with a new instance that has members equivalent to the members of the added instance.

instance.java


import java.util.ArrayList;
import java.util.List;

class Person {
    public String name;
    Person(String name){
        this.name = name;
    }
}
public class instance {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Taro"));
        System.out.println("After addition(person) : " + personList.size());
        personList.remove(new Person("Taro"));
        System.out.println("After deletion(person) : " + personList.size());
    }
}

At first glance it seems to work, but the result is that the elements of ʻArrayList` are not removed.

result.java


After addition(person) : 1
After deletion(person) : 1

It is true that the members of the instance have an equivalence relationship, but if the memory address of the instance is different, the memory address of the member should be different, so it is judged that they are not equivalent because they are not equal values. Therefore, it seems that the ʻequalsmethod of the original object class is judged asfalse`.

So, as mentioned at the beginning, we will override the ʻequals` method to fix the above bug.

instance.java


class Man {
    public String name;
    Man(String name){
        this.name = name;
    }
    public boolean equals(Object o){
        if(o == this) return true;
        if(o == null) return false;
        if(!(o instanceof Man)) return false;
        Man man = (Man) o ;
        if(!(this.name.equals(man.name))) return false;
        return true;
    }
}
public class instance {
    public static void main(String[] args) {
        List<Man> manList = new ArrayList<Man>();
        manList.add(new Man("Taro"));
        System.out.println("After addition(man) : " + manList.size());
        manList.remove(new Man("Taro"));
        System.out.println("After deletion(man) : " + manList.size());
    }
}

This time, the ʻequals method is defined in advance in the Man class. Specifically, if the comparison source and the comparison target object have the same type and the members (name) are equivalent, true` is returned.

result.java


After addition(man) : 1
After deletion(man) : 0

Yes, it now works as intended as described above.

However, overriding each one as described above is also quite troublesome. Isn't it enough to remove the relevant element while turning it with for as shown below without overriding it separately? Thinking: thinking:

instancce.java


import java.util.ArrayList;
import java.util.List;

class Person {
    public String name;
    Person(String name){
        this.name = name;
    }
}
public class instance {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Taro"));

        System.out.println("before deleting the for statement(person) : " + personList.size());
        for(int i=0; i<personList.size(); i++){
            Person person = personList.get(i);
            String name = person.name;
            if(name.equals("Taro")){
                personList.remove(person);
            }
        }
        System.out.println("After deleting the for statement(person) : " + personList.size());
    }
}

result.java


before deleting the for statement(person) : 1
After deleting the for statement(person) : 0

After that, for those who say that the description of the ʻequals method is verbose and it is troublesome to write it one by one, if you use ʻEqualsBuilder of the library called commons-lang, if all the members are equivalent, the instance is also considered to be equivalent. It will make a judgment. I have not tried it this time, but the description method is as follows.

equalsBuilder.java


import org.apache.commons.lang3.builder.*;

class Man {
    public String name;
    Man(String name){
        this.name = name;
    }
    public boolean equals(Object o){
        return EqualsBuilder.reflectionEquals(this,o);
    }
}

bonus

This time, I posted the method of specifying an element with the for statement and deleting it, but when this is turned with the extended for statement, an error called ConcurrentModificationException occurs. This error is returned when the collection to be created is manipulated by ʻadd, remove, etc. when ʻiterator is created.

For details, refer to the links below. .. .. (It's a hassle to write ...) https://qiita.com/sig_Left/items/eebea3f88a16dcfa2983 https://teratail.com/questions/16901

Recommended Posts

[Note] Java: Is it necessary to override equals for equality judgment?
Things to watch out for in Java equals
[Java] Is it unnecessary to check "identity" in the implementation of the equals () method?
[Java] Note the case where equals is false but == is ture.
Is it possible to automatically generate Getters / Setters with Java Interface?
[For beginners] Ruby is said to be ruby, but what about it?
Things to note for newcomers to write readable code during Java development
When calling sshpass from Java with shell etc., it seems that it is necessary to have a path.
[Java] Points to note with Arrays.asList ()
How to use equality and equality (how to use equals)
My note: Introducing Java to Ubuntu
[Java] Nowadays, the extended for statement is not exclusively for List, isn't it?
[Java] I want to make it easier because it is troublesome to input System.out.println.