package java.util; /** * Maps keys to objects. It has a fixed-size table, so don't * expect it to scale well. */ public class Hashtable { private static final int TABLE_SIZE = 32; private Object[] iTable = new Object[TABLE_SIZE]; public Hashtable() { } public synchronized Object get (Object aKey) { Object pElement = iTable[getTableIndex(aKey)]; if (pElement == null) return null; KeyValuePair pKeyValuePair = getKeyValuePair (pElement, aKey); if (pKeyValuePair == null) return null; return pKeyValuePair.iValue; } public synchronized Object put (Object aKey, Object aValue) { Object r; int pIndex = getTableIndex (aKey); Object pElement = iTable[pIndex]; KeyValuePair pKeyValuePair = null; if (pElement != null) pKeyValuePair = getKeyValuePair (pElement, aKey); if (pKeyValuePair != null) r = pKeyValuePair.iValue; else { r = null; pKeyValuePair = new KeyValuePair(); pKeyValuePair.iKey = aKey; pKeyValuePair.iValue = aValue; } if (pElement == null) { iTable[pIndex] = pKeyValuePair; } else if (pElement == pKeyValuePair) { pKeyValuePair.iValue = aValue; } else if (pElement instanceof KeyValuePair) { Vector pVector = new Vector(); pVector.addElement (pElement); pVector.addElement (pKeyValuePair); iTable[pIndex] = pVector; } else { // pElement must be a Vector ((Vector) pElement).addElement (pKeyValuePair); } return r; } /** * * @return An Enumeration object containing all keys for this Hashtable */ public Enumeration keys() { return new Enumeration() { int cur = 0; /* Our Hashtable stores more than one object in iTable if * getTableIndex() hashes it to the same slot. When this happens * it stores multiple items in a Vector. In this case, nextElement() * needs to keep track of which vector it is at via curVector. */ int curVector = -1; public boolean hasMoreElements() { /* Difficult to work with our current Hashtable code due to iTable gaps.*/ int i=cur; // This little detour is to check if there are any more objects in a Vector (if used) if(i < TABLE_SIZE && iTable[i] instanceof Vector) { Vector v = (Vector)iTable[i]; if(curVector + 1 >= v.size()) i++; } for(;i<TABLE_SIZE;i++) if(iTable[i] != null) return true; return false; } public Object nextElement() { /* Difficult to work with our current Hashtable code due to iTable gaps. */ // Go thru iTable until object found while(cur < TABLE_SIZE) { if(iTable[cur] instanceof KeyValuePair) { KeyValuePair kvp = (KeyValuePair)iTable[cur]; cur++; if(kvp != null) return kvp.iKey; } else if (iTable[cur] instanceof Vector) { curVector++; while(curVector >= 0) { Vector v = (Vector)iTable[cur]; if (curVector >= v.size()) { curVector = -1; break; } KeyValuePair kvp = (KeyValuePair)v.elementAt(curVector); if(kvp == null) { curVector = -1; } else { return kvp.iKey; } } } cur++; } return null; } }; } private KeyValuePair getKeyValuePair (Object aPivot, Object aKey) { if (aPivot instanceof Vector) { Vector pVec = (Vector) aPivot; int pSize = pVec.size(); for (int i = 0; i < pSize; i++) { KeyValuePair pPair = (KeyValuePair) pVec.elementAt (i); if (aKey.equals (pPair.iKey)) return pPair; } return null; } // Not a Vector, must be a lone KeyValuePair KeyValuePair pPair = (KeyValuePair) aPivot; if (aKey.equals (pPair.iKey)) return pPair; return null; } private int getTableIndex (Object aKey) { int pHash = aKey.hashCode(); if (pHash < 0) pHash = -pHash; return pHash % TABLE_SIZE; } private static class KeyValuePair { Object iKey; Object iValue; } }