class InternCache
    extends ConcurrentHashMap<String,String> // since 2.3
{
    private static final long serialVersionUID = 1L;

    /**
     * Size to use is somewhat arbitrary, so let's choose something that's
     * neither too small (low hit ratio) nor too large (waste of memory).
     *<p>
     * One consideration is possible attack via colliding {@link String#hashCode};
     * because of this, limit to reasonably low setting.
     *<p>
     * Increased to 200 (from 100) in 2.18
     */
    private final static int DEFAULT_MAX_ENTRIES = 280;

    public final static InternCache instance = new InternCache();

    /**
     * As minor optimization let's try to avoid "flush storms",
     * cases where multiple threads might try to concurrently
     * flush the map.
     */
    private final ReentrantLock lock = new ReentrantLock();

    public InternCache() { this(DEFAULT_MAX_ENTRIES, 0.8f, 4); }

    public InternCache(int maxSize, float loadFactor, int concurrency) {
        super(maxSize, loadFactor, concurrency);
    }

    public String intern(String input) {<FILL_FUNCTION_BODY>}
}

        String result = get(input);
        if (result != null) { return result; }

        /* 18-Sep-2013, tatu: We used to use LinkedHashMap, which has simple LRU
         *   method. No such functionality exists with CHM; and let's use simplest
         *   possible limitation: just clear all contents. This because otherwise
         *   we are simply likely to keep on clearing same, commonly used entries.
         */
        if (size() >= DEFAULT_MAX_ENTRIES) {
            /* As of 2.18, the limit is not strictly enforced, but we do try to
             * clear entries if we have reached the limit. We do not expect to
             * go too much over the limit, and if we do, it's not a huge problem.
             * If some other thread has the lock, we will not clear but the lock should
             * not be held for long, so another thread should be able to clear in the near future.
             */
            if (lock.tryLock()) {
                try {
                    if (size() >= DEFAULT_MAX_ENTRIES) {
                        clear();
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
        result = input.intern();
        put(result, result);
        return result;
    
<methods>public void <init>() ,public void <init>(int) ,public void <init>(Map<? extends java.lang.String,? extends java.lang.String>) ,public void <init>(int, float) ,public void <init>(int, float, int) ,public void clear() ,public java.lang.String compute(java.lang.String, BiFunction<? super java.lang.String,? super java.lang.String,? extends java.lang.String>) ,public java.lang.String computeIfAbsent(java.lang.String, Function<? super java.lang.String,? extends java.lang.String>) ,public java.lang.String computeIfPresent(java.lang.String, BiFunction<? super java.lang.String,? super java.lang.String,? extends java.lang.String>) ,public boolean contains(java.lang.Object) ,public boolean containsKey(java.lang.Object) ,public boolean containsValue(java.lang.Object) ,public Enumeration<java.lang.String> elements() ,public Set<Entry<java.lang.String,java.lang.String>> entrySet() ,public boolean equals(java.lang.Object) ,public void forEach(BiConsumer<? super java.lang.String,? super java.lang.String>) ,public void forEach(long, BiConsumer<? super java.lang.String,? super java.lang.String>) ,public void forEach(long, BiFunction<? super java.lang.String,? super java.lang.String,? extends U>, Consumer<? super U>) ,public void forEachEntry(long, Consumer<? super Entry<java.lang.String,java.lang.String>>) ,public void forEachEntry(long, Function<Entry<java.lang.String,java.lang.String>,? extends U>, Consumer<? super U>) ,public void forEachKey(long, Consumer<? super java.lang.String>) ,public void forEachKey(long, Function<? super java.lang.String,? extends U>, Consumer<? super U>) ,public void forEachValue(long, Consumer<? super java.lang.String>) ,public void forEachValue(long, Function<? super java.lang.String,? extends U>, Consumer<? super U>) ,public java.lang.String get(java.lang.Object) ,public java.lang.String getOrDefault(java.lang.Object, java.lang.String) ,public int hashCode() ,public boolean isEmpty() ,public KeySetView<java.lang.String,java.lang.String> keySet() ,public KeySetView<java.lang.String,java.lang.String> keySet(java.lang.String) ,public Enumeration<java.lang.String> keys() ,public long mappingCount() ,public java.lang.String merge(java.lang.String, java.lang.String, BiFunction<? super java.lang.String,? super java.lang.String,? extends java.lang.String>) ,public static KeySetView<K,java.lang.Boolean> newKeySet() ,public static KeySetView<K,java.lang.Boolean> newKeySet(int) ,public java.lang.String put(java.lang.String, java.lang.String) ,public void putAll(Map<? extends java.lang.String,? extends java.lang.String>) ,public java.lang.String putIfAbsent(java.lang.String, java.lang.String) ,public U reduce(long, BiFunction<? super java.lang.String,? super java.lang.String,? extends U>, BiFunction<? super U,? super U,? extends U>) ,public Entry<java.lang.String,java.lang.String> reduceEntries(long, BiFunction<Entry<java.lang.String,java.lang.String>,Entry<java.lang.String,java.lang.String>,? extends Entry<java.lang.String,java.lang.String>>) ,public U reduceEntries(long, Function<Entry<java.lang.String,java.lang.String>,? extends U>, BiFunction<? super U,? super U,? extends U>) ,public double reduceEntriesToDouble(long, ToDoubleFunction<Entry<java.lang.String,java.lang.String>>, double, java.util.function.DoubleBinaryOperator) ,public int reduceEntriesToInt(long, ToIntFunction<Entry<java.lang.String,java.lang.String>>, int, java.util.function.IntBinaryOperator) ,public long reduceEntriesToLong(long, ToLongFunction<Entry<java.lang.String,java.lang.String>>, long, java.util.function.LongBinaryOperator) ,public java.lang.String reduceKeys(long, BiFunction<? super java.lang.String,? super java.lang.String,? extends java.lang.String>) ,public U reduceKeys(long, Function<? super java.lang.String,? extends U>, BiFunction<? super U,? super U,? extends U>) ,public double reduceKeysToDouble(long, ToDoubleFunction<? super java.lang.String>, double, java.util.function.DoubleBinaryOperator) ,public int reduceKeysToInt(long, ToIntFunction<? super java.lang.String>, int, java.util.function.IntBinaryOperator) ,public long reduceKeysToLong(long, ToLongFunction<? super java.lang.String>, long, java.util.function.LongBinaryOperator) ,public double reduceToDouble(long, ToDoubleBiFunction<? super java.lang.String,? super java.lang.String>, double, java.util.function.DoubleBinaryOperator) ,public int reduceToInt(long, ToIntBiFunction<? super java.lang.String,? super java.lang.String>, int, java.util.function.IntBinaryOperator) ,public long reduceToLong(long, ToLongBiFunction<? super java.lang.String,? super java.lang.String>, long, java.util.function.LongBinaryOperator) ,public java.lang.String reduceValues(long, BiFunction<? super java.lang.String,? super java.lang.String,? extends java.lang.String>) ,public U reduceValues(long, Function<? super java.lang.String,? extends U>, BiFunction<? super U,? super U,? extends U>) ,public double reduceValuesToDouble(long, ToDoubleFunction<? super java.lang.String>, double, java.util.function.DoubleBinaryOperator) ,public int reduceValuesToInt(long, ToIntFunction<? super java.lang.String>, int, java.util.function.IntBinaryOperator) ,public long reduceValuesToLong(long, ToLongFunction<? super java.lang.String>, long, java.util.function.LongBinaryOperator) ,public java.lang.String remove(java.lang.Object) ,public boolean remove(java.lang.Object, java.lang.Object) ,public java.lang.String replace(java.lang.String, java.lang.String) ,public boolean replace(java.lang.String, java.lang.String, java.lang.String) ,public void replaceAll(BiFunction<? super java.lang.String,? super java.lang.String,? extends java.lang.String>) ,public U search(long, BiFunction<? super java.lang.String,? super java.lang.String,? extends U>) ,public U searchEntries(long, Function<Entry<java.lang.String,java.lang.String>,? extends U>) ,public U searchKeys(long, Function<? super java.lang.String,? extends U>) ,public U searchValues(long, Function<? super java.lang.String,? extends U>) ,public int size() ,public java.lang.String toString() ,public Collection<java.lang.String> values() <variables>private static final int ABASE,private static final int ASHIFT,private static final long BASECOUNT,private static final long CELLSBUSY,private static final long CELLVALUE,private static final int DEFAULT_CAPACITY,private static final int DEFAULT_CONCURRENCY_LEVEL,static final int HASH_BITS,private static final float LOAD_FACTOR,private static final int MAXIMUM_CAPACITY,static final int MAX_ARRAY_SIZE,private static final int MAX_RESIZERS,private static final int MIN_TRANSFER_STRIDE,static final int MIN_TREEIFY_CAPACITY,static final int MOVED,static final int NCPU,static final int RESERVED,private static final int RESIZE_STAMP_BITS,private static final int RESIZE_STAMP_SHIFT,private static final long SIZECTL,private static final long TRANSFERINDEX,static final int TREEBIN,static final int TREEIFY_THRESHOLD,private static final jdk.internal.misc.Unsafe U,static final int UNTREEIFY_THRESHOLD,private volatile transient long baseCount,private volatile transient int cellsBusy,private volatile transient java.util.concurrent.ConcurrentHashMap.CounterCell[] counterCells,private transient EntrySetView<java.lang.String,java.lang.String> entrySet,private transient KeySetView<java.lang.String,java.lang.String> keySet,private volatile transient Node<java.lang.String,java.lang.String>[] nextTable,private static final java.io.ObjectStreamField[] serialPersistentFields,private static final long serialVersionUID,private volatile transient int sizeCtl,volatile transient Node<java.lang.String,java.lang.String>[] table,private volatile transient int transferIndex,private transient ValuesView<java.lang.String,java.lang.String> values