How to write an entry for an unordered pair in Java

I need to have Set (HashSet) so that if I insert a pair (a, b) , and if (b, a) already in the set, the insert will simply be ignored. How to do it in Java?

Many thanks!

+7
source share
5 answers

Well, that depends on the hashCode() and equals() method of your Pair class. They need to ignore order.

Set itself is a good example of a class that ignores order for equality - you can see the AbstractSet code. If the order of the pair does not matter even beyond the equality comparison, you can simply save the HashSet (each with two elements) in its own set. It is best to wrap it in the form of data:

  public class UnorderedPair<T> { private final Set<T> set; public UnorderedPair(T a, T b) { set = new HashSet<T>(); set.add(a); set.add(b); } public boolean equals(Object b) { //...delegate to set } public int hashCode() { return set.hashCode(); } } 
+7
source
 final class Pair<T> { private final Set<T> elements = new LinkedHashSet<T>(); Pair(T a, T b) { elements.add(a); if (!elements.add(b)) throw new IllegalArgumentException(); } @Override public int hashCode() { return elements.hashCode(); } @Override public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof Pair<?>)) return false; return elements.equals(((Pair<?>) obj).elements); } } 
+3
source

Define the Pair class whose equals and hashCode methods are based on both a and b in such a way that the order of a and b is irrelevant and uses a HashSet .

+2
source

Override the equals() and hashCode() methods of the Pair class to treat both (a, b) and (b, a) as equal.

0
source

Since none of the answers mention this approach, I would like to add this approach:

 public class UnorderedPair<T> { final T first, second; public UnorderedPair(T first, T second) { this.first = first; this.second = second; } @Override public boolean equals(Object o) { if (!(o instanceof UnorderedPair)) return false; UnorderedPair<T> up = (UnorderedPair<T>) o; return (up.first == this.first && up.second == this.second) || (up.first == this.second && up.second == this.first); } @Override public int hashCode() { int hashFirst = first.hashCode(); int hashSecond = second.hashCode(); int maxHash = Math.max(hashFirst, hashSecond); int minHash = Math.min(hashFirst, hashSecond); // return Objects.hash(minHash, maxHash); // the above line also works but I tend to avoid this to avoid unnecessary auto-boxing return minHash * 31 + maxHash; } } 

Note that you should adhere to the common hashCode() and equals() contract:

  • If you override hashCode() or equals() you should also override another method.
  • If equals returns true for 2 objects, then the hashCode() method should return the same int value for both objects.
  • If hashCode() returns the same int for 2 objects, then it is not necessarily true that the equals() method returns true .

The above implementation of the equals() and hashCode() method provides this.

0
source

Source: https://habr.com/ru/post/906265/


All Articles