aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Understanding List.remove() and List.contains() Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Understanding List.remove() and List.contains()" Watch "Understanding List.remove() and List.contains()" New topic
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: 3170
    
  10
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.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Understanding List.remove() and List.contains()
 
Similar Threads
Problem in displaying multiple search results
Sorting through Comparable(Very Urgent)
Problem with refresh() method of EntityManamger in JPA
why am i getting a null value on fetching from map
equal( ) and hashCode( ) Examples