Using java Collection <E> .contains (Object o) when overriding equals method

I have List <Person> objects where a person is defined like this

public Person { private firstName; private lastName; //getter and setter methods public boolean equals(Object obj) { return lastName.equals(obj.toString()); } } 

Now I want to see if this List <Person> contains a specific name.

 if(myList.contains("Smith")) System.out.println("yay!"); 

However, the method of specifying the method contains what returns true when (o == null? E == null: o.equals (e)). Thus, in this case, instead of the Person.equals (String) parameter, String.equals (Person) is used. Is there an easy way to fix this or should I write my own logic for contains?

+4
source share
5 answers

Is there an easy way to fix this ...

No, not using Collection.contains .

Under contract equals implementation must be symmetrical:

for any non-zero reference values x and y , x.equals(y) should return true if and only if y.equals(x) returns true .

This means that returning anything other than false for somePerson.equals(someString) is a direct breach of contract.

... or do I need to write my own logic for the content?

Yes. Use the for loop:

 for (Person p : myList) if (p.getLastName().equals("Smith")) return true; return false; 

or, if you are using Java 8,

 return myList.stream().anyMatch(p -> p.getLastName().equals("Smith")); 
+3
source

One way is to create a List<String> view using the existing myList and continue.

 final List<Person> myList = yourList; List<String> strView = new AbstractList<String>() { String get(int i) { return myList.get(i).getLastName(); } int size() { return myList.size(); } }; if(strView.contains("Smith")) System.out.println("Yaay"); 
+2
source

You will need to write your own logic for this.

I would highly recommend that when overriding the equals method, you stick to the API defined by java Object # equals. The equals method is used in many places (hashmaps, to name one), and using other logic will lead you to a lot of problems later.

+1
source

Since you are not looking for Person , the most communicative solution would be to have a method that specifically indicates that it is looking for a last name, for example containsLastName or something else, or take an example from Person and use this as an object similar to the criterion.

0
source

Another option here is to use Guava Iterables.any

  Predicate<Person> findMe(final String name){ return new Predicate<Person>(){ public boolean apply(Person input){ return input.lastname.equals(name); } } } boolean contains = Iterables.any(myList, findMe("Smith")); 

or

 Function<Person, String> lastName = new Function<Person, String>(){ public String apply(Person input){ return input.lastName; } } boolean contains = Lists.transform(myList, lastName).contains("Smith"); 
0
source

All Articles