com.adobe.xfa.ut.SymbolTable Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa.ut;
/**
* This class is used to optimize the use of String.intern() when it is
* used on a sequence of strings that are frequently repeated.
*
* The call to String.intern() is a relatively expensive operation because
* of synchronization and the creation of weak references.
* This class caches strings that it has already interned to avoid calling
* repeating the call to intern.
*
* The implementation uses a String[] to implement the hash table. The reason
* for using this implementation instead of a collection class is to avoid
* the overhead of creation of many entry objects, as most hash set implementations
* would do. This implementation also doesn't attempt to resize the table if
* it becomes full. In that case, it simply stops caching new entries, and
* falls back to simply interning any uncached strings.
*
* @author Andy Neilson
*
* @exclude from published api.
*/
public final class SymbolTable {
/**
* The table of Strings that have already been seen and interned.
*/
private final String[] table = new String[TABLE_SIZE];
/**
* The number of Strings that have been added to the table.
*/
private int size;
/**
* The size of the table. Because of the way the hash code is calculated,
* this needs to be a power of two.
*/
private final static int TABLE_SIZE = 1024;
/**
* Mask off the lower bits of the hash code to generate an index into table.
*/
private final static int HASH_MASK = TABLE_SIZE - 1;
/**
* The number of entries after which we will stop adding symbols to the table.
*/
private final static int THRESHOLD = (TABLE_SIZE * 2) / 3;
/**
* Constructs a new, empty SymbolTable.
*/
public SymbolTable() {
}
/**
* Return an interned version of a symbol.
* @param symbol a string to be interned.
* @return the interned string.
*/
public String internSymbol(String symbol) {
int i = symbol.hashCode() & HASH_MASK;
String item;
while ((item = table[i]) != null) {
if (item.equals(symbol)) {
return item;
}
// Linear probe
i = (i + 1) % TABLE_SIZE;
}
// This symbol isn't in the table, so intern it.
symbol = symbol.intern();
// If we have room, cache the symbol so we don't need
// to intern it if we see it again.
if (size < THRESHOLD) {
table[i] = symbol;
size++;
}
return symbol;
}
}