Java tutorial
// ArrayDictionary.java // $Id: ArrayDictionary.java,v 1.16 2000/08/16 21:37:57 ylafon Exp $ // (c) COPYRIGHT MIT and INRIA, 1996. // Please first read the full copyright statement in file COPYRIGHT.html import java.util.Dictionary; import java.util.Enumeration; import java.util.Vector; import java.io.DataInputStream; import java.io.InputStream; import java.io.PrintStream; /** * Random-access dictionary: * like a dictionary but with a certain Vector-ness to it * Besides all the methods from Dictionary, it also has methods that * permit direct access to the nth element or nth key. * Should be used with care...it's not too well tested yet, and it * is very exposed. * <p>This class does <em>not</em> provide thread-safeness, for the sake of * efficiency, again it should be used with care ! * @author Antonio Ramírez */ public class ArrayDictionary extends Dictionary implements Cloneable { /** The array of keys */ protected Object[] keys; /** The array of corresponding values */ protected Object[] values; /** How many real elements are in */ protected int nelems; /** By how much to grow */ protected int incr; /** * Create an ArrayDictionary using default values for initial size and * increment. */ public ArrayDictionary() { this(10, 10); } /** * Create an ArrayDictionary using the given initial size. * (The increment is set to the same value). * @param init The initial size */ public ArrayDictionary(int init) { this(init, init); } /** * Clone this array dictionary. * <p>As for hashtables, a shallow copy is made, the keys and elements * themselves are <em>not</em> cloned. * @return The clone. */ public Object clone() { try { ArrayDictionary cl = (ArrayDictionary) super.clone(); cl.values = new Object[values.length]; System.arraycopy(values, 0, cl.values, 0, values.length); cl.keys = new Object[values.length]; System.arraycopy(keys, 0, cl.keys, 0, keys.length); return cl; } catch (CloneNotSupportedException ex) { throw new InternalError(); } } /** * Create an ArrayDictionary using the given initial size and * the given increment for growing the array. * @param init the initial size * @param incr the increment */ public ArrayDictionary(int init, int incr) { keys = new Object[init]; values = new Object[init]; this.incr = incr; nelems = 0; } /** * Create an ArrayDictionary, contructing the arrays of keys and * values from the two given vectors. * The two vectors should have the same size. * The increment is set to the number of elements. * @param keys the vector of keys * @param values the vector of values */ public ArrayDictionary(Vector keys, Vector values) { this(keys, values, values.size()); } /** * Create an ArrayDictionary, contructing the arrays of keys and * values from the two given vectors. * The two vectors should have the same size. * @param keys the vector of keys * @param values the vector of values * @param incr the increment for growing the arrays */ public ArrayDictionary(Vector keys, Vector values, int incr) { this.incr = incr; nelems = keys.size(); this.keys = new Object[nelems]; this.values = new Object[nelems]; keys.copyInto(this.keys); values.copyInto(this.values); } /** * Create an ArrayDicitonary, <em>using</em> (not copying) the given pair * of arrays as keys and values. The increment is set to the length of the * arrays. * @param keys the array of keys * @param values the array of values */ public ArrayDictionary(Object[] keys, Object[] values) { this(keys, values, values.length); } /** * Create an ArrayDicitonary, <em>using</em> (not copying) the given pair * of arrays as keys and values. * @param keys the array of keys * @param values the array of values * @param incr the increment for growing the arrays */ public ArrayDictionary(Object[] keys, Object[] values, int incr) { this.incr = incr; nelems = keys.length; this.keys = keys; this.values = values; } protected final void grow() { grow(keys.length + incr); } protected void grow(int newCapacity) { Object[] newKeys = new Object[newCapacity]; Object[] newVals = new Object[newCapacity]; System.arraycopy(keys, 0, newKeys, 0, keys.length); System.arraycopy(values, 0, newVals, 0, values.length); keys = newKeys; values = newVals; } /** * Returns an enumeration of the elements of the dictionary. * @return the enumeration */ public Enumeration elements() { return new ArrayEnumeration(values, nelems); } /** * Returns the value that maps to the given key. * @param key the key * @return the value */ public Object get(Object key) { int n, i; for (i = 0, n = 0; i < keys.length; i++) { if (n >= nelems) break; if (keys[i] == null) continue; if (keys[i].equals(key)) return values[i]; n++; } return null; } /** * "Optimized" method to obtain the values * corresponding to several keys, in one swoop. * @param rKeys An array of requested keys * @return An array of corresponding values */ public Object[] getMany(Object[] rKeys) { Object[] rValues = new Object[rKeys.length]; int i, n; for (i = 0, n = 0; i < keys.length; i++) { if (n >= nelems) break; if (keys[i] == null) continue; inloop: for (int j = 0; j < rKeys.length; j++) if (keys[i].equals(rKeys[j])) { rValues[j] = values[i]; break inloop; } n++; } return rValues; } /** * Are there any entries in the dictionary? * @return <strong>true</strong> if there are no entries, * <strong>false></strong> otherwise. */ public final boolean isEmpty() { return nelems == 0; } /** * Increases the capacity of this dictionary to at least the * specified number of key/value mappings. * @param minCapacity the desired minimum capacity */ public final void ensureCapacity(int minCapacity) { if (minCapacity > keys.length) grow(minCapacity); } /** * Returns an enumeration of the keys of the dictionary. * @return the enumeration */ public Enumeration keys() { return new ArrayEnumeration(keys, nelems); } /** * Adds a mapping between a key and a value to the dictionary. * Will grow the arrays if necessary. * @param key the key * @param value the corresponding value * @return the previous value corresponding to the key, or null if * the key is new. */ public Object put(Object key, Object value) { int empty = -1; int i, n; for (i = 0, n = 0; i < keys.length; i++) { if (n >= nelems) break; if (keys[i] == null) { empty = i; continue; } if (keys[i].equals(key)) { Object prev = values[i]; values[i] = value; return prev; } n++; } if (empty != -1) { keys[empty] = key; values[empty] = value; nelems++; } else { grow(); keys[nelems] = key; values[nelems++] = value; } return null; } /** * Removes a key (and its value) from the dictionary; * @param key the key to remove * @return the value that used to map to that key */ public Object remove(Object key) { int i, n; for (i = 0, n = 0; i < keys.length; i++) { if (n >= nelems) break; if (keys[i] == null) continue; if (keys[i].equals(key)) { nelems--; Object prev = values[i]; keys[i] = values[i] = null; return prev; } n++; } return null; } /** * Returns the number of elements in the dictionary * @return the number of elements */ public final int size() { return nelems; } /** * Returns the maximum number of keys the dictionary can hold * without reallocating an array. * @return the capacity of the dictionary */ public final int capacity() { return keys.length; } /** * Returns the nth key. * @param n the index of the desired key * @return the nth key, or null if no key in that place. */ public final Object keyAt(int n) { return keys[n]; } /** * Returns the nth element (value). * @param n the index of the desired element * @return the nth element, or null if no element in that place. */ public final Object elementAt(int n) { return values[n]; } /** * Sets the element at the nth place in the array. * @param n the index of the element to change * @param newVal the value to change it to * @return the old value */ public Object setElementAt(int n, Object newVal) { Object prev = values[n]; values[n] = newVal; return prev; } /** * Removes the nth mapping (key/value pair) in the dictionary. * @param n the index of the element to remove * @return the old value of the element at the nth place */ public Object removeElementAt(int n) { if (values[n] != null) { Object prev = values[n]; values[n] = keys[n] = null; nelems--; return prev; } else return null; } /** * Creates a string representation of the dictionary * @return the string representation. */ public String toString() { StringBuffer buf = new StringBuffer(100); buf.append('['); for (int i = 0; i < keys.length; i++) { if (keys[i] == null) continue; buf.append(keys[i]); buf.append('='); buf.append(values[i]); buf.append(' '); } buf.append(']'); return buf.toString(); } /** * A kludge for testing ArrayDictionary */ public static void main(String[] args) { try { PrintStream out = System.out; DataInputStream in = new DataInputStream(System.in); String line = null; out.print("n ? "); out.flush(); line = in.readLine(); int n = Integer.parseInt(line); ArrayDictionary ad = new ArrayDictionary(n); String key = null, value = null; while (true) { out.print("action ? "); out.flush(); line = in.readLine(); switch (line.charAt(0)) { case 'p': case 'P': out.print("key ? "); out.flush(); key = in.readLine(); out.print("value ? "); out.flush(); value = in.readLine(); value = (String) ad.put(key, value); out.println("old: " + value); break; case 'r': case 'R': out.print("key ? "); out.flush(); key = in.readLine(); value = (String) ad.remove(key); out.println("old: " + value); break; case 'g': case 'G': out.print("key ? "); out.flush(); key = in.readLine(); value = (String) ad.get(key); out.println("value: " + value); break; case 'd': case 'D': out.println(ad.toString()); break; case 'q': case 'Q': return; } } } catch (Exception ex) { ex.printStackTrace(); } } } //ArrayEnumeration.java //$Id: ArrayEnumeration.java,v 1.3 2000/08/16 21:37:57 ylafon Exp $ //(c) COPYRIGHT MIT and INRIA, 1996. //Please first read the full copyright statement in file COPYRIGHT.html /** Iterates through array skipping nulls. */ class ArrayEnumeration implements Enumeration { private int nelems; private int elemCount; private int arrayIdx; private Object[] array; public ArrayEnumeration(Object[] array) { this(array, array.length); } public ArrayEnumeration(Object[] array, int nelems) { arrayIdx = elemCount = 0; this.nelems = nelems; this.array = array; } public final boolean hasMoreElements() { return elemCount < nelems; } public final Object nextElement() { while (array[arrayIdx] == null && arrayIdx < array.length) arrayIdx++; if (arrayIdx >= array.length) throw new RuntimeException(); elemCount++; return array[arrayIdx++]; } }