如何在Java中为无序对写一个集合

时间:2012-01-18 05:15:32

标签: java

我需要一个Set(HashSet),这样如果我插入一对(a, b)并且如果(b, a)已经在集合中,则插入将被忽略。如何在Java中执行此操作?

非常感谢!

5 个答案:

答案 0 :(得分:7)

嗯,这取决于hashCode()课程的equals()Pair方法。他们需要忽略秩序。

Set本身就是一个忽略了相等顺序的类的好例子 - 你可以查看AbstractSet的代码。如果即使在相等比较之外,对的顺序也无关紧要,您只需在集合中存储HashSet s(每个都有两个元素)。最好将其包装在数据类型中:

 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();
     }
}

答案 1 :(得分:3)

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);
  }
}

答案 2 :(得分:2)

定义一个类Pair,其equalshashCode方法基于ab的方式,顺序为a }和b无关紧要,并使用HashSet

答案 3 :(得分:0)

重写equals()类的hashCode()Pair方法,将(a,b)和(b,a)视为相等。

答案 4 :(得分:0)

由于没有答案提到这种方法,因此我想添加这种方法:

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;
    }
}

请注意,应遵守hashCode()equals()的一般合同:

  • 如果您要覆盖hashCode()equals(),则也应覆盖另一种方法。
  • 如果equals返回2个对象的true,则hashCode()方法应该为两个对象返回相同的int
  • 如果hashCode()对于2个对象返回相同的int,则equals()方法返回true不一定是正确的。

以上equals()hashCode()方法的实现确保了这一点。