Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Contains() method not calling Overridden equals method

I am having an issue where I make an ArrayList of Foo objects, I override the equals method, and I cannot get the contains method to call the equals method. I have tried overriding equals and hashcode together, but it still doesn't work. I'm sure there is a logical explanation to why this is, but I cannot figure it out at the moment on my own lol. I just want a way to see if the list contains the specified id.

Here's some code:

import java.util.ArrayList; import java.util.List;  public class Foo {      private String id;       public static void main(String... args){         Foo a = new Foo("ID1");         Foo b = new Foo("ID2");         Foo c = new Foo("ID3");         List<Foo> fooList = new ArrayList<Foo>();         fooList.add(a);         fooList.add(b);         fooList.add(c);         System.out.println(fooList.contains("ID1"));         System.out.println(fooList.contains("ID2"));         System.out.println(fooList.contains("ID5"));     }         public Foo(String id){         this.id = id;     }      @Override     public boolean equals(Object o){         if(o instanceof String){             String toCompare = (String) o;             return id.equals(toCompare);         }         return false;     }        @Override     public int hashCode(){         return 1;     } } 

OUTPUT: false false false

like image 464
Reid Mac Avatar asked Feb 16 '12 20:02

Reid Mac


People also ask

Can the equals method be overridden?

You can override the equals method on a record, if you want a behavior other than the default. But if you do override equals , be sure to override hashCode for consistent logic, as you would for a conventional Java class.

What happens if equals is not overridden?

equals() : If you only override the equals method, if a. equals(b) is true it means the hashCode of a and b must be the same but that does not happen since you did not override the hashCode method. Note : hashCode() method of Object class always returns a new hashCode for each object.

What are equals () and hashCode () overriding rules?

if a class overrides equals, it must override hashCode. when they are both overridden, equals and hashCode must use the same set of fields. if two objects are equal, then their hashCode values must be equal as well. if the object is immutable, then hashCode is a candidate for caching and lazy initialization.

What is equals () method in Java?

Java String equals() Method The equals() method compares two strings, and returns true if the strings are equal, and false if not. Tip: Use the compareTo() method to compare two strings lexicographically.


1 Answers

This is because your equals() is not symmetric:

new Foo("ID1").equals("ID1"); 

but

"ID1".equals(new Foo("ID1")); 

is not true. This violates the equals() contract:

The equals method implements an equivalence relation on non-null object references:

  • [...]

  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

It is not reflexive either:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
Foo foo = new Foo("ID1"); foo.equals(foo)  //false! 

@mbockus provides correct implementation of equals():

public boolean equals(Object o){   if(o instanceof Foo){     Foo toCompare = (Foo) o;     return this.id.equals(toCompare.id);   }   return false; } 

but now you must pass instance of Foo to contains():

System.out.println(fooList.contains(new Foo("ID1"))); System.out.println(fooList.contains(new Foo("ID2"))); System.out.println(fooList.contains(new Foo("ID5"))); 

Finally you should implement hashCode() to provide consistent results (if two objects are equal, they must have equal hashCode()):

@Override public int hashCode() {     return id.hashCode(); } 
like image 126
Tomasz Nurkiewicz Avatar answered Oct 13 '22 11:10

Tomasz Nurkiewicz