/*
  * 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;
 }
 @Override
 public String toString() {
   StringBuffer buffer = new StringBuffer("{"); // $NON-NLS-1$
   for (int i = 0, length = this.values.length; i < length; i++) {
     HashedReference<T> value = this.values[i];
     if (value != null) {
       Object ref = value.get();
       if (ref != null) {
         buffer.append(ref.toString());
         buffer.append(", "); // $NON-NLS-1$
       }
     }
   }
   buffer.append("}"); // $NON-NLS-1$
   return buffer.toString();
 }
 /*
  * 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;
 }
  private void addValue(HashedReference<T> value) {
    Object obj = value.get();
    if (obj == null) return;
    int valuesLength = this.values.length;
    int index = (value.hashCode() & 0x7FFFFFFF) % valuesLength;
    HashedReference<T> currentValue;
    while ((currentValue = this.values[index]) != null) {
      if (obj.equals(currentValue.get())) {
        return;
      }
      index = (index + 1) % valuesLength;
    }
    this.values[index] = value;

    // assumes the threshold is never equal to the size of the table
    if (++this.elementSize > this.threshold) rehash();
  }
  /*
   * 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;
  }
 private void cleanupGarbageCollectedValues() {
   HashedReference<?> toBeRemoved;
   while ((toBeRemoved = (HashedReference<?>) this.referenceQueue.poll()) != null) {
     int hashCode = toBeRemoved.hashCode();
     int valuesLength = this.values.length;
     int index = (hashCode & 0x7FFFFFFF) % valuesLength;
     HashedReference<T> currentValue;
     while ((currentValue = this.values[index]) != null) {
       if (currentValue == toBeRemoved) {
         // replace the value at index with the last value with the
         // same hash
         int sameHash = index;
         int current;
         while ((currentValue = this.values[current = (sameHash + 1) % valuesLength]) != null
             && currentValue.hashCode() == hashCode) sameHash = current;
         this.values[index] = this.values[sameHash];
         this.values[sameHash] = null;
         this.elementSize--;
         break;
       }
       index = (index + 1) % valuesLength;
     }
   }
 }