| Author |
Understanding List.remove() and List.contains()
|
Shawn Smith
Ranch Hand
Joined: Feb 22, 2011
Posts: 41
|
|
Given the following code (which I've condensed for readability, probably much to my woe):
public class Employee
{
public String firstName;
public String lastName;
public String employeeID;
public Employee(String first, String last, String ID)
{
firstName = first;
lastName = last;
employeeID = ID;
}
public boolean equals(Object o)
{
if (o instanceof String)
{
return employeeID.equals((String)o);
}
else if (o instanceof Employee)
{
return employeeID.equals(((Employee)o).employeeID);
}
return false;
}
public int hashCode()
{
return employeeID.hashCode();
}
public static void main(String [] args)
{
List<Employee> le = new ArrayList<Employee>();
le.add(new Employee("Thing", "One", "1"));
le.add(new Employee("Thing", "Two", "2"));
le.add(new Employee("Thing", "Three", "3"));
String outsideObject = "3";
if (le.contains(outsideObject))
System.out.println("First test success");
else if (le.contains(new Employee(null, null, outsideObject)))
System.out.println("Second test success");
}
}
The result evaluates to Second test success because the collection uses the outsideObject's equals rather than the contained objects equals. So my question's are:
1. Is there a way to change this behavior so that the contained object's equals is being used? It seems the extra construction of what could be a complex object just to be used as the comparator may be excessive. (I'm sure this is a no, but have been proven wrong before)
2. Is there a way outside of associative collections to get the behavior I'm looking for? I'd like to avoid extra copies of data values such as employeeID (as in Map<String, Employee> emps; where the String is another reference to the employeeID. I could remove the extra copy, but would have to repackage if returning to some user.
Thanks in advance,
Shawn
|
 |
Shawn Smith
Ranch Hand
Joined: Feb 22, 2011
Posts: 41
|
|
Hit Quote rather than Code. Sorry for the repost. Note to self, always use the preview button...
|
 |
Hareendra Reddy
Ranch Hand
Joined: Jan 09, 2011
Posts: 173
|
|
Is there a way to change this behavior so that the contained object's equals is being used? It seems the extra construction of what could be a complex object just to be used as the comparator may be excessive. (I'm sure this is a no, but have been proven wrong before)
But the equals method of Employee class violates the equals contract i.e it is not symmetric.
May be i did not understand your point precisely.waiting for experts comments.
|
 |
Joanne Neal
Rancher
Joined: Aug 05, 2005
Posts: 3011
|
|
Shawn Smith wrote:1. Is there a way to change this behavior so that the contained object's equals is being used?
Probably not, but it shouldn't really matter. The only reason it does in this case is because you have a badly implemented equals method. If you have a look at the Javadoc for the Object.equals method, it says
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.
This does not hold true here because String.equals will never return true if the object passed to the method is not a String.
i.e. will always print false.
|
Joanne
|
 |
Shawn Smith
Ranch Hand
Joined: Feb 22, 2011
Posts: 41
|
|
That's what I expected, I was just hoping to avoid an additional copy with the associative solution. Forgive an old c++ guy for trying to simulate custom comparators in the "find-like" clauses .
I would much prefer something similar to std::find_if where I can provide an external predicate for matching, but haven't been able to find the equivalent in Java (except for Collections.binarySearch() but I'm looking for the first instance in an unsorted list.)
Guess I'll roll my own loop or switch to the associative solution.
Thanks for the response.
Shawn
|
 |
dennis deems
Ranch Hand
Joined: Mar 12, 2011
Posts: 808
|
|
Shawn Smith wrote:That's what I expected, I was just hoping to avoid an additional copy with the associative solution. Forgive an old c++ guy for trying to simulate custom comparators in the "find-like" clauses  .
I would much prefer something similar to std::find_if where I can provide an external predicate for matching, but haven't been able to find the equivalent in Java (except for Collections.binarySearch() but I'm looking for the first instance in an unsorted list.)
Guess I'll roll my own loop or switch to the associative solution.
Thanks for the response.
Shawn
The map really is the best solution IMO. It does everything you want to do, and if you are smart about instantiating your Strings, then your concern about redundant data is unnecessary.
|
 |
 |
|
|
subject: Understanding List.remove() and List.contains()
|
|
|