class BinaryIdentitySet<T> {

  protected final T o1;
  protected final T o2;
  protected final int hashCode;

  public BinaryIdentitySet(T o1, T o2) {
    this.o1 = o1;
    this.o2 = o2;
    this.hashCode = computeHashCode();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public int hashCode() {
    return hashCode;
  }

  private int computeHashCode() {
    int result = 1;
    // must be commutative
    result += System.identityHashCode(o1);
    result += System.identityHashCode(o2);
    return result;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean equals(Object obj) {<FILL_FUNCTION_BODY>}

  public T getO1() {
    return o1;
  }

  public T getO2() {
    return o2;
  }

  @Override
  public String toString() {
    return "IdentityPair " + o1 + "," + o2;
  }
}

    if (this == obj) {
      return true;
    }
    if (obj == null || this.getClass() != obj.getClass()) {
      return false;
    }
    final BinaryIdentitySet<?> other = (BinaryIdentitySet<?>) obj;
    // must be commutative
    return (this.o1 == other.o1 || this.o1 == other.o2) && (this.o2 == other.o2 || this.o2 == other.o1);
  
<no_super_class>