kal
kal

Reputation: 29381

Contains for List of Pair

  List<Pair<String, String> > lp = new ArrayList<Pair<String, String> >();
  lp.add(new Pair("1", "2"));

How should I check if the list lp contains 1 and 2 i.e the Pair ("1", "2").

Upvotes: 7

Views: 8440

Answers (2)

andersoj
andersoj

Reputation: 22884

Your Pair class needs to implement equals() and hashCode() and you're all set. List.contains() is implemented in terms of the type's equals() method. See the API for List.contains(). (Edited a bit to address comments from @maaartinus, whose answer you should read b/c the observations are solid, and it's a bit ridiculous for me to fold them in here. As maaartinus points out, a best-practice here would be to avoid error-prone manual definitions for equals and hashcode, and instead build on Guava's helper functions for nullable equals and hashCode for n objects).

final class Pair<T> {

   final T left;
   final T right;

   public Pair(T left, T right)
   {
     if (left == null || right == null) { 
       throw new IllegalArgumentException("left and right must be non-null!");
     }
     this.left = left;
     this.right = right;
   }

   public boolean equals(Object o)
   {
     // see @maaartinus answer
     if (! (o instanceof Pair)) { return false; }
     Pair p = (Pair)o;
     return left.equals(p.left) && right.equals(p.right);
   } 

   public int hashCode()
   {
      return 7 * left.hashCode() + 13 * right.hashCode();
   } 
}

With suitable equals(), you can now do:

  lp.add(new Pair("1", "2"));
  assert lp.contains(new Pair("1","2"));

Responding to the comments below, perhaps it would be good to include a good reference for "Why do I need to implement hashCode()?"

Upvotes: 7

maaartinus
maaartinus

Reputation: 46432

The implementation in the answer by andersoj

 return left != null && right != null && left.equals(p.left) && right.equals(p.right);

is wrong: The null tests clearly suggest that null is a legal value for left and right. So there are at least two problems there:

  • new Pair(null, null).hashCode() throws NPE
  • new Pair(null, null) does NOT equal to itself!

Have a look at Guava class Objects for a correct implementation. Use it or write a static helper methods like

public static boolean equal(Object a, Object b) {
    return a==b || a!=null && a.equals(b);
}
public static int hashCode(Object a) {
    return a==null ? 0 : a.hashCode();
}

and always use them.

Never ever write equals containing a null test.

It's to easy to blow it, and nobody noticed it. Using the Helper, it's trivial to get it right:

public boolean equals(Object o)  {
    if (!(o instanceof Pair)) return false;
    Pair p = (Pair) o;
    return Helper.equals(left, p.left) && Helper.equals(right, p.right);
} 

public int hashCode() {
    return 7 * Helper.hashCode(left) + 13 * Helper.hashCode(right);
} 

Of course, forbidding nulls in the constructor is an option, too.

Upvotes: 1

Related Questions