«^»
3.4. The methods contains, indexOf, lastIndexof and remove

Given the method called iterator, it is very easy to find out whether a collection contains a particular value. Suppose we have a List which contains a collection of values all of which are Person objects. Suppose we now want to write a method called iIsInList that returns true if and only if the List object pList has an element which points to an object representing a person with the name pName:

private static boolean iIsInList(final List pList, final String pName)
{
   final Iterator tIterator = pList.iterator();
   while (tIterator.hasNext())
   {
      final Person tPerson = (Person)tIterator.next();
      if (pName.equals(tPerson.getName()))
      {
         return true;
      }
   }
   return false;
}
Here is an example of a call of this method:
boolean tFound = iIsInList(tList, "Dick");

However, it is a waste of time declaring this method as the List interface has a method called contains that does this job for us. So instead we can use:

Person tTargetPerson  = new Person("Dick%%");
boolean tFound = tList.contains(tTargetPerson);

Each of the methods:

public boolean    contains(Object pValue);
public int         indexOf(Object pValue);
public int     lastIndexOf(Object pValue);
public boolean      remove(Object pValue);
(of the List interface) requires the target list to be searched from the head (or the tail for lastIndexOf) of the list to find an element of the list that has the same value as the object pointed to by pValue. The WWW pages that document this interface (javaapi:java/util/List.html) state that each of these methods looks for an element e such that pValue.equals(e). Because the parameter e is of type Object, the method being used here has the header:
public boolean equals(Object pObject);
Because pValue, the target of the equals, is actually of the class Person, and because the class declaration for Person declares a method with the above header then that method will be used when any of these four methods is executed.

So, when executing:

Person tTargetPerson  = new Person("Dick%%");
boolean tFound = tList.contains(tTargetPerson);
the contains method searches to see if it can find an element which equals that of tTargetPerson. It will use the method called equals declared in the class Person. This method says that two Person objects are equal if and only if the names are the same. For this to work, the class Person must provide a method with the header:
public boolean equals(Object pObject);
rather than (or in addition to):
public boolean equals(Person pPerson);

The method contains is not particularly useful if you want to do something to an element of the collection. Instead, it is better to use indexOf which will return the position of the element. Here is an example:

final Person tTargetPerson  = new Person("Dick%%");
final int tPosition = tList.indexOf(tTargetPerson);
if (tPosition>=0)
{
   final Person tPerson = (Person)tList.get(tPosition);
   tPerson.setName("Richard");
   ...
}
Because the Collections API uses the share approach, tPerson is pointing to the same object that an element of tList is pointing to. So, the statement:
tPerson.setName("Richard");
also changes one of the elements of tList (which may or may not be what you want). If you prefer not to alter the element of the list, the result of the call of get should be cloned:
final Person tPerson = new Person((Person)tList.get(tPosition));
tPerson.setName("Richard");
...

It is also possible to use indexOf when you want to remove an element from a list: first find the appropriate position in the list and then remove the element at that position:

Person tTargetPerson  = new Person("Dick%%");
int tPosition = tList.indexOf(tTargetPerson);
if (tPosition>=0)
{
   tList.remove(tPosition);
}
However, the List interface has another remove method which is more suitable (as it eliminates the need to call indexOf). So, the above is better coded as:
Person tTargetPerson  = new Person("Dick%%");
tList.remove(tTargetPerson);