/*
  * Return the object that is in this set and that is equals to the given
  * object. Return null if not found.
  */
 public T get(T obj) {
   cleanupGarbageCollectedValues();
   int valuesLength = this.values.length;
   int index = (obj.hashCode() & 0x7FFFFFFF) % valuesLength;
   HashedReference<T> currentValue;
   while ((currentValue = this.values[index]) != null) {
     T referent;
     if (obj.equals(referent = currentValue.get())) {
       return referent;
     }
     index = (index + 1) % valuesLength;
   }
   return null;
 }
 /*
  * Removes the object that is in this set and that is equals to the given
  * object. Return the object that was in the set, or null if not found.
  */
 public Object remove(T obj) {
   cleanupGarbageCollectedValues();
   int valuesLength = this.values.length;
   int index = (obj.hashCode() & 0x7FFFFFFF) % valuesLength;
   HashedReference<T> currentValue;
   while ((currentValue = this.values[index]) != null) {
     Object referent;
     if (obj.equals(referent = currentValue.get())) {
       this.elementSize--;
       this.values[index] = null;
       rehash();
       return referent;
     }
     index = (index + 1) % valuesLength;
   }
   return null;
 }
  /*
   * Adds the given object to this set. If an object that is equals to the
   * given object already exists, do nothing. Returns the existing object or
   * the new object if not found.
   */
  public T add(T obj, int referenceType) {
    cleanupGarbageCollectedValues();
    int index = (obj.hashCode() & 0x7FFFFFFF) % this.values.length;
    HashedReference<T> currentValue;
    while ((currentValue = this.values[index]) != null) {
      T referent;
      if (obj.equals(referent = currentValue.get())) {
        return referent;
      }
      index = (index + 1) % this.values.length;
    }
    this.values[index] = toReference(referenceType, obj);

    // assumes the threshold is never equal to the size of the table
    if (++this.elementSize > this.threshold) rehash();

    return obj;
  }