public final Object add(Object key, Object value) {
        int bucketIndex = (key.hashCode() & Integer.MAX_VALUE) % numBuckets;
        int bucketSize = bucketSizes[bucketIndex]++;

        // Discard an entry from the bucket if it's already at the maximum bucket size.

        Object discardedObject = bucketSize == maxBucketSize ?
                        discardFromBucket(bucketIndex, --bucketSize) :
                        null; 

        // Add the new entry.  We might temporarily exceed the maximum entry limit by 1.  In
        // that case we will end up removing an entry before returning.

        values[bucketIndex][bucketSize] = value;
        keys[bucketIndex][bucketSize] = key;

        // Update the MRU/LRU pointer for the current bucket.  This involves removing the
        // current pointer, if it exists, and creating a new MRU/LRU pointer at the MRU end
        // of the list.

        // Remove current pointer, if there is one.

        int n, p;

        if ((n = next[bucketIndex]) != BEFORE_LRU) {
            previous[n] = p = previous[bucketIndex];
            next[p] = n;
        }

        // Create a new MRU/LRU pointer at the MRU end of the list.

        p = previous[AFTER_MRU];
        previous[AFTER_MRU] = next[p] = bucketIndex;

        next[bucketIndex] = AFTER_MRU;
        previous[bucketIndex] = p;

        // If we exceeded the upper limit on entries in the cache map, remove a LRU entry and
        // return it.  Otherwise, if we had to discard an entry to keep from exceeding the
        // maximum bucket size, return that entry.  Otherwise, return null.

        return ++numEntries > maxEntries ? removeLRU() : discardedObject; 
    }
public final Object add ( Object key , Object value ) { int bucketIndex = ( key . hashCode ( ) & Integer . MAX_VALUE ) % numBuckets ; int bucketSize = bucketSizes [ bucketIndex ] ++ ; Object discardedObject = bucketSize == maxBucketSize ? discardFromBucket ( bucketIndex , -- bucketSize ) : null ; values [ bucketIndex ] [ bucketSize ] = value ; keys [ bucketIndex ] [ bucketSize ] = key ; int n , p ; if ( ( n = next [ bucketIndex ] ) != BEFORE_LRU ) { previous [ n ] = p = previous [ bucketIndex ] ; next [ p ] = n ; } p = previous [ AFTER_MRU ] ; previous [ AFTER_MRU ] = next [ p ] = bucketIndex ; next [ bucketIndex ] = AFTER_MRU ; previous [ bucketIndex ] = p ; return ++ numEntries > maxEntries ? removeLRU ( ) : discardedObject ; }
Add an entry to the map consisting of the specified (key, value) pair. A key is allowed
to simultaneously map to multiple values. If the maximum number of entries for the
CacheMap is exceeded, an entry is discarded.

@param key the key.
@param value the value.

@return the discarded value, or null if none.