/** * Increases the capacity of and internally reorganizes this SymbolTable, in order to accommodate * and access its entries more efficiently. This method is called automatically when the number of * keys in the SymbolTable exceeds this hashtable's capacity and load factor. */ protected void rehash() { int oldCapacity = fBuckets.length; SREntry[] oldTable = fBuckets; int newCapacity = oldCapacity * 2 + 1; SREntry[] newTable = new SREntry[newCapacity]; fThreshold = (int) (newCapacity * fLoadFactor); fBuckets = newTable; fTableSize = fBuckets.length; for (int i = oldCapacity; i-- > 0; ) { for (SREntry old = oldTable[i]; old != null; ) { SREntry e = old; old = old.next; SREntryData data = (SREntryData) e.get(); if (data != null) { int index = hash(data.characters, 0, data.characters.length) % newCapacity; if (newTable[index] != null) { newTable[index].prev = e; } e.next = newTable[index]; e.prev = null; newTable[index] = e; } else { fCount--; } } } }
/** * Adds the specified symbol to the symbol table and returns a reference to the unique symbol. If * the symbol already exists, the previous symbol reference is returned instead, in order * guarantee that symbol references remain unique. * * @param buffer The buffer containing the new symbol. * @param offset The offset into the buffer of the new symbol. * @param length The length of the new symbol in the buffer. */ public String addSymbol(char[] buffer, int offset, int length) { clean(); // search for identical symbol int bucket = hash(buffer, offset, length) % fTableSize; OUTER: for (SREntry entry = fBuckets[bucket]; entry != null; entry = entry.next) { SREntryData data = (SREntryData) entry.get(); if (data == null) { continue; } if (length == data.characters.length) { for (int i = 0; i < length; i++) { if (buffer[offset + i] != data.characters[i]) { continue OUTER; } } return data.symbol; } } if (fCount >= fThreshold) { // Rehash the table if the threshold is exceeded rehash(); bucket = hash(buffer, offset, length) % fTableSize; } // add new entry String symbol = new String(buffer, offset, length).intern(); SREntry entry = new SREntry(symbol, buffer, offset, length, fBuckets[bucket], bucket, fReferenceQueue); fBuckets[bucket] = entry; ++fCount; return symbol; } // addSymbol(char[],int,int):String
/** * Adds the specified symbol to the symbol table and returns a reference to the unique symbol. If * the symbol already exists, the previous symbol reference is returned instead, in order * guarantee that symbol references remain unique. * * @param symbol The new symbol. */ public String addSymbol(String symbol) { clean(); // search for identical symbol int bucket = hash(symbol) % fTableSize; for (SREntry entry = fBuckets[bucket]; entry != null; entry = entry.next) { SREntryData data = (SREntryData) entry.get(); if (data == null) { continue; } if (data.symbol.equals(symbol)) { return data.symbol; } } if (fCount >= fThreshold) { // Rehash the table if the threshold is exceeded rehash(); bucket = hash(symbol) % fTableSize; } // add new entry symbol = symbol.intern(); SREntry entry = new SREntry(symbol, fBuckets[bucket], bucket, fReferenceQueue); fBuckets[bucket] = entry; ++fCount; return symbol; } // addSymbol(String):String
private void initialize(SREntry next, int bucket) { this.next = next; if (next != null) { next.prev = this; } this.prev = null; this.bucket = bucket; }
/** * Returns true if the symbol table already contains the specified symbol. * * @param buffer The buffer containing the symbol to look for. * @param offset The offset into the buffer. * @param length The length of the symbol in the buffer. */ public boolean containsSymbol(char[] buffer, int offset, int length) { // search for identical symbol int bucket = hash(buffer, offset, length) % fTableSize; OUTER: for (SREntry entry = fBuckets[bucket]; entry != null; entry = entry.next) { SREntryData data = (SREntryData) entry.get(); if (data == null) { continue; } if (length == data.characters.length) { for (int i = 0; i < length; i++) { if (buffer[offset + i] != data.characters[i]) { continue OUTER; } } return true; } } return false; } // containsSymbol(char[],int,int):boolean
/** * Returns true if the symbol table already contains the specified symbol. * * @param symbol The symbol to look for. */ public boolean containsSymbol(String symbol) { // search for identical symbol int bucket = hash(symbol) % fTableSize; int length = symbol.length(); OUTER: for (SREntry entry = fBuckets[bucket]; entry != null; entry = entry.next) { SREntryData data = (SREntryData) entry.get(); if (data == null) { continue; } if (length == data.characters.length) { for (int i = 0; i < length; i++) { if (symbol.charAt(i) != data.characters[i]) { continue OUTER; } } return true; } } return false; } // containsSymbol(String):boolean