Java/Collections Data Structure/Dictionary

Материал из Java эксперт
Перейти к: навигация, поиск

Random-access dictionary

  
// 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&iacute;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++] ;
 }
}