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