Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

equals() method for classes with bidirectional association

I am trying to implement equals method for Java classes Book and Chapter in my application. Book has a set of Chapters, while a Chapter has an associated Book. The bidirectional association is shown as below:

class Book{
    private String isbn;
    private String name;
    private Date publishDate;
    private Set<Chapter> chapters;
    ...

    public boolean equals(Object o){
        if(o == this){
            return true;
        }
        if (!(o instanceof Book)){
            return false;
        }
        Book book = (Book)o;
        if( (this.isbn.equals(book.getIsbn()) ) && (this.name.equals(book.getName())) &&(this.publishDate.equals(book.getPublishDate())) &&(this.chapters.equals(book.getChapters())) ){
            return true;
        }else{
            return false;
        }

    }
}

Now I tried to implement equals for Chapter:

public class Chapter {
    private String title;
    private Integer noOfPages;
    private Book book;
    ...

    public boolean equals(Object o){
         if(o == this){
            return true;
        }
        if (!(o instanceof Chapter)){
            return false;
        }
        Chapter ch = (Chapter)o;
        if((this.title.equals(book.getTitle())) && (this.noOfPages.intValue()== book.getNoOfPages().intValue())  ){
            return true;
        }else{
            return false;
        }
    }

}

Here, I am wondering if I need to compare the book field as well. Wouldn't that start an infinite loop? What is the correct way of implementing the equals method for such bidirectional associations?

like image 306
markjason72 Avatar asked May 26 '11 18:05

markjason72


People also ask

What is equals () method in Java?

The equals() method compares two strings, and returns true if the strings are equal, and false if not.

What is bidirectional association in Java?

In a bidirectional relationship, each entity has a relationship field or property that refers to the other entity. Through the relationship field or property, an entity class's code can access its related object. If an entity has a related field, the entity is said to “know” about its related object.

Which class is an equals method?

equals() is a method defined in Object class. == operator compares the memory locations of two objects and returns a boolean value whereas . equals() is used to compare the two objects by some business logic and returns a boolean value.

How do we implement hashCode () and equals ()?

Java hashCode() An object hash code value can change in multiple executions of the same application. If two objects are equal according to equals() method, then their hash code must be same. If two objects are unequal according to equals() method, their hash code are not required to be different.


4 Answers

A book should be equal to another book only if their ISBNs are equal. So implement the book equals only based on that field.

For the chapter - compare the chapter number and the owning Book

like image 93
Bozho Avatar answered Nov 09 '22 18:11

Bozho


(I'm assuming this is Java) In the Chapter class equals method, you could just compare the book references (that is, using ==, not equals). This only compare references, so it would avoid an infinite loop. However, if you Clone books sometimes, this approach would fail.

An even better way to solve this specific case would be to compare not the books, but their ISBN, since that is an unique identifier for a Book.

In general, it is better to avoid bidirectional dependencies like this. One way is to have one of the two classes implement an interface, so as not to use it directly.

like image 25
dario_ramos Avatar answered Nov 09 '22 18:11

dario_ramos


From a modeling perspective, the chapter is part of the book. So although you have references in both directions, the book is "stronger" than the chapter.

When you have part-of relationships like with Book and Chapter, the part (Chapter) sometimes takes the whole (Book) into account when defining equals(). But not the other way round.

So clearly, the book would not use its chapters to define equals(). The chapter might use the book. That depends on the model.

like image 27
Wolfgang Avatar answered Nov 09 '22 19:11

Wolfgang


You have to choose a Book field as a ID (like ISBN). Then, in Chapter equals, you can do a thing like

book.getISBN().equals(other.book.getISBN())
like image 41
Alberto Avatar answered Nov 09 '22 20:11

Alberto