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?
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
xandy,x.equals(y)should returntrueif and only ify.equals(x)returnstrue.
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")); 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"); 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.
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.
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");