Using java Collection<E>.contains(Object o) when overriding equals method
I have a List<Person> objects where person is defined like so
public Person {
private firstName;
private lastName;
//getter and setter methods
public boolean equals(Object obj) {
return la开发者_Go百科stName.equals(obj.toString());
}
}
Now I want to see if this List<Person> contains a certain last name.
if(myList.contains("Smith"))
System.out.println("yay!");
However the way the contains method is specified is that is returns true when (o==null ? e==null : o.equals(e)). So in this instance it is using String.equals(Person) instead of Person.equals(String). Is there a simple way of fixing this or do I have to write my own logic for contains?
Is there a simple way of fixing this...
No, not using Collection.contains
.
By the contract of equals
the implementation must be symmetric:
for any non-null reference values
x
andy
,x.equals(y)
should returntrue
if and only ify.equals(x)
returnstrue
.
This means that returning any thing else than false
for somePerson.equals(someString)
is a direct violation of the contract.
...or do I have to write my own logic for contains?
Yes. Use a for loop:
for (Person p : myList)
if (p.getLastName().equals("Smith"))
return true;
return false;
or, if you're using Java 8,
return myList.stream().anyMatch(p -> p.getLastName().equals("Smith"));
One way would be to construct a List<String>
view using the existing myList and go ahead.
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'll have to write your own logic for this.
I would strongly advise that when you override 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 a different logic will get you into lots of trouble later on.
Since you're not looking for a Person
the most communicative solution would be to have a method that specifically indicates it's looking for a last name, like containsLastName
or whatever, or take an example Person
and use it as a criteria-like object.
Another option here is to use Guava's 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");
精彩评论