docs: public String display() {
          StringBuffer sb = new StringBuffer();
          DecimalFormat f = new java.text.DecimalFormat("'  '000");
  
          sb.append(AdapterUtil.EOLN).append(this);
          sb.append(AdapterUtil.EOLN).append("Number of entries:   ").append(numEntries);
          sb.append(AdapterUtil.EOLN).append("Maximum entries:     ").append(maxEntries);
          sb.append(AdapterUtil.EOLN).append("Number of buckets:   ").append(numBuckets);
          sb.append(AdapterUtil.EOLN).append("Maximum bucket size: ").append(maxBucketSize); 
          sb.append(AdapterUtil.EOLN).append("Number of discards:  ").append(numDiscards); 
  
          sb.append(AdapterUtil.EOLN);
          sb.append(AdapterUtil.EOLN).append("BUCKET SIZE PREV NEXT");
          sb.append(AdapterUtil.EOLN); 
  
          for (int i = 0; i < numBuckets; i++) {
              sb.append(f.format(i));
              sb.append(f.format(bucketSizes[i]));
              sb.append(f.format(previous[i]));
              sb.append(f.format(next[i]));
              sb.append(AdapterUtil.EOLN); 
  
              for (int j = 0; j < bucketSizes[i]; j++)
                  sb.append("                      ").append(Integer.toHexString(values[i][j].hashCode())).append(' ').append(keys[i][j]).append(AdapterUtil.EOLN); 
          }
  
          sb.append(f.format(BEFORE_LRU)).append("  LRU     ").append(f.format(next[BEFORE_LRU])).append(AdapterUtil.EOLN); 
          sb.append(f.format(AFTER_MRU)).append("  MRU").append(f.format(previous[AFTER_MRU])).append(AdapterUtil.EOLN); 
  
          return new String(sb);
      }
  
      /**
       * Returns the maximum number of entries that can be kept in the cache.
       * 
       * @return the maximum number of entries that can be kept in the cache.
       */
      public final int getMaxSize() {
          return maxEntries;
      }
  
      /**
       * Remove an entry. If the key maps to multiple values, only one is removed.
       * 
       * @param key the key.
       * 
       * @return the value that was removed, or null if none is found.
       */
      public final Object remove(Object key) {
          int bucketIndex = (key.hashCode() & Integer.MAX_VALUE) % numBuckets;
          Object[] bucketKeys = keys[bucketIndex]; 
          int bucketSize = bucketSizes[bucketIndex];
  
          // Look through the entries in the bucket to find one that matches for removal.
  
          for (int i = bucketSize - 1; i >= 0; i--) {
              if (bucketKeys[i].equals(key)) {
                  // If we emptied the bucket then remove its MRU/LRU entry.
  
                  if ((bucketSizes[bucketIndex] = --bucketSize) == 0) {
                      // Nothing will be left in the bucket, so remove its MRU/LRU entry.
                      int n = next[bucketIndex];
                      int p = previous[n] = previous[bucketIndex];
                      next[p] = n;
  
                      next[bucketIndex] = previous[bucketIndex] = BEFORE_LRU;
                  }
  
                  numEntries--;
  
                  bucketKeys[i] = bucketKeys[bucketSize];
                  bucketKeys[bucketSize] = null;
  
                  Object[] bucketValues = values[bucketIndex];
                  Object value = bucketValues[i];
                  bucketValues[i] = bucketValues[bucketSize];
                  bucketValues[bucketSize] = null;
  
                  return value;
              }
          }
  
          // Entry was not found for removal.
  
          return null;
      }
  
      /**
       * Remove all entries in the map.
       * 
       * @return a list of all values that were removed.
       */
      public final Object[] removeAll() {
          Object[] list = new Object[numEntries];
          numEntries = 0;
          Object[] bucketValues;
          Object[] bucketKeys; 
  
          // Empty all buckets.
  
          try {
              for (int i = numBuckets, counter = 0; i > 0;) {
                  for (int j = bucketSizes[--i]; j > 0;) {
                      bucketValues = values[i];
                      bucketKeys = keys[i];
  
                      bucketKeys[--j] = null; 
  
                      list[counter++] = bucketValues[j];
                      bucketValues[j] = null;
                  }
  
                  bucketSizes[i] = 0;
              }
  
              // Clear all MRU/LRU entries for buckets.
              for (int i = 0; i <= AFTER_MRU; i++)
                  next[i] = previous[i] = BEFORE_LRU;
          } catch (ArrayIndexOutOfBoundsException ioobX) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) { 
                  Tr.debug(this, tc, "ArrayIndexOutOfBoundsException is caught during removeAll() of the cachMap ", this);
                  Tr.debug(this, tc, "Possible causes:");
                  Tr.debug(this, tc, "multithreaded access of JDBC objects by the Application");
                  Tr.debug(this, tc, "Application is closing JDBC objects in a finalize()");
                  Tr.debug(this, tc, "Exception is: ", ioobX);
              }
  
              throw ioobX;
          }
  
          return list;
      }
  
      /**
       * Remove an entry from the least recently used bucket. This method requires no explicit
       * synchronization because the calling method (add) is already synchronized.
       * As of  all synchronization was removed.
       * 
       * @return the value that was removed.
       */
      private final Object removeLRU() {
          int bucketIndex = next[BEFORE_LRU];
          Object[] bucketValues = values[bucketIndex];
          Object[] bucketKeys = keys[bucketIndex]; 
          int bucketSize = --bucketSizes[bucketIndex];
  
          numEntries--;
  
          // Choose an entry in the LRU bucket to remove.  The numDiscards counter is used to
          // reduce the chance of always choosing the same index.
  
          int indexToRemove = (numDiscards++ & Integer.MAX_VALUE) % (bucketSize + 1);
  
          Object value = bucketValues[indexToRemove];
  
          // If we emptied the bucket then remove its MRU/LRU entry.
  
          if (bucketSize == 0) {
              int n = next[bucketIndex];
              int p = previous[n] = previous[bucketIndex];
              next[p] = n;
  
              next[bucketIndex] = BEFORE_LRU;
              //previous[bucketIndex] = BEFORE_LRU; // already true
  
              // As long as we've already determined the new bucket size is 0, do some optimized
              // bucket clearing.
  
              bucketValues[0] = null;
              bucketKeys[0] = null;
          }
          else {// We didn't empty the bucket.  Remove the first entry and replace with the last.
              bucketValues[indexToRemove] = bucketValues[bucketSize];
              bucketValues[bucketSize] = null;
  
              bucketKeys[indexToRemove] = bucketKeys[bucketSize];
              bucketKeys[bucketSize] = null;
          }
  
          return value;
      }
  
      /**
       * @return the number of entries in the map.
       */
      public final int size() {
          return numEntries;
      }
  }