Contains a list of pairs

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

How to check if the list contains lp 1 and 2 ie Pair ("1", "2").

+8
java collections
source share
2 answers

Your Pair class must implement equals() and hashCode() , and you are all set up. List.contains() is implemented in terms of a method of type equals() . See the API for List.contains() . (Edited a bit to respond to comments from @maaartinus, the answer to which you should read b / c. The observations are strong, and it’s a little funny for me to put them here. As maaartinus points out, the best practice here would be to avoid error-prone manual definitions for equals and hashcode and instead create Guava helper functions for null-value 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, it might be nice to include a good link for "Why do I need to implement hashCode() ?"

+7
source share

Implementation in answer by andersoj

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

false: null tests clearly indicate that null is the legal value for left and right. So there are at least two problems:

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

See the Guava class Objects for a proper implementation. Use it or write 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 write equals containing a null test.

It is easy to explode, and no one noticed. Using Helper, it is trivial to figure this out:

 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, disabling zeros in the constructor is also an option.

+1
source share

All Articles