code: public synchronized <U extends T> U put(U obj) {
          if (obj == null) {
              return null;
          }
  
          Entry<T>[] entries = mEntries;
          int hash = hashCode(obj);
          int index = (hash & 0x7fffffff) % entries.length;
          for (Entry<T> e = entries[index], prev = null; e != null; e = e.mNext) {
              T iobj = e.get();
              if (iobj == null) {
                  // Clean up after a cleared Reference.
                  if (prev == null) {
                      entries[index] = e.mNext;
                  } else {
                      prev.mNext = e.mNext;
                  }
                  mSize--;
              } else if (e.mHash == hash && obj.getClass() == iobj.getClass() && equals(obj, iobj)) {
                  // Found canonical instance.
                  return (U) iobj;
              } else {
                  prev = e;
              }
          }
  
          if (mSize >= mThreshold) {
              cleanup();
              if (mSize >= mThreshold) {
                  rehash();
                  entries = mEntries;
                  index = (hash & 0x7fffffff) % entries.length;
              }
          }
  
          entries[index] = new Entry<T>(this, obj, hash, entries[index]);
          mSize++;
          return obj;
      }
docs: Pass in a candidate canonical object and get a unique instance from this
  set. The returned object will always be of the same type as that passed
  in. If the object passed in does not equal any object currently in the
  set, it will be added to the set, becoming canonical.
  
  @param obj candidate canonical object; null is also accepted