⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hashtabledecorable.java

📁 Java数据结构开发包
💻 JAVA
字号:
/*
  Copyright (c) 1999, 2000 Brown University, Providence, RI
  
                            All Rights Reserved
  
  Permission to use, copy, modify, and distribute this software and its
  documentation for any purpose other than its incorporation into a
  commercial product is hereby granted without fee, provided that the
  above copyright notice appear in all copies and that both that
  copyright notice and this permission notice appear in supporting
  documentation, and that the name of Brown University not be used in
  advertising or publicity pertaining to distribution of the software
  without specific, written prior permission.
  
  BROWN UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  FITNESS FOR ANY PARTICULAR PURPOSE.  IN NO EVENT SHALL BROWN
  UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
*/

package jdsl.core.ref;

import jdsl.core.api.*;



/**
 * An implementation of Decorable using a hashtable.
 * 
 * @author Mike Boilen (mgb)
 *         <!-- initial version -->
 * @author Benoit Hudson (bh) 
 *         <!-- lazy-allocate table, smaller serialization, load factor=1 -->
 * @author Ryan Shaun Baker (rsb)
 *         <!-- port -->
 * @version JDSL 2.1.1 
 */
public class HashtableDecorable implements Decorable, java.io.Serializable {

  /**
   * A list of primes to grow to.  It's longer than you could possibly
   * need (it tops out at 1.6 billion).
   */
  private static final int[] PRIMES={ 
    5,          11,         37,        53,         97,
    193,        389,        769,       1543,       3079,
    6151,       12289,      24593,     49157,      98317,
    196613,     393241,     786433,    1572869,    3145739,
    6291469,    12582917,   25165843,  50331653,   100663319,  
    201326611,  402653189,  805306457, 1610612741
  };

  /**
   * Next cell in the list of primes.  It will grow to be the length
   * indicated by this subscript.
   */
  private transient int iNextPrime;

  /**
   * The current size of this container.  This differs from capactiy
   */
  private transient int iSize;

  /**
   * The current capacity of this container.
   */
  private transient int iCapacity;

  /**
   * The default initial capacity of this hashtable.
   */
  private static final int DEFAULT_INITIAL_CAPACITY=0;

  /**
   * Default next prime for resizing.
   */
  private static final int DEFAULT_NEXT_PRIME=0;

  /**
   * The underlying array.
   */
  private transient HashtableData[] iData;


  
  public HashtableDecorable () {
    initEmpty();
  }
    
  private final void initEmpty() {
    iData = null;
    iCapacity = 0;
    iSize = 0;
    iNextPrime = 0;
  }
    
  private final void initialAllocate() {
    iCapacity = PRIMES[iNextPrime++];
    iData = new HashtableData[iCapacity];
  }



  // public methods

  /**
   * Destroys a decoration.
   *
   * @exception InvalidAttributeException if the decoration does not exist.
   */
  public final Object destroy (Object key) throws
    InvalidAttributeException, CoreException {
    if(size()==0) {
      throw new InvalidAttributeException("Empty Decorable\n"+
					  "\tDecorable "+this+"\n"+
					  "\tkey       "+key);
    }

    // find the bucket
    int index = hash(key)%capacity();
    HashtableData current  = iData[index];
    HashtableData previous = null;
    Object ret = null;

    // search for the key in the bucket
    while(current!=null) {
      if(current.iKey==key) {
	// found; remove the node from the list
	ret=current.iElement;
	if(previous==null)
	  iData[index]=current.iNext;
	else
	  previous.iNext=current.iNext;
	iSize--;
	return ret;
      }
      previous=current;
      current=current.iNext;
    }
    throw new InvalidAttributeException("Attribute does not exist\n"+
					"\tDecorable "+this+"\n"+
					"\tkey       "+key);
  }


  /**
   * Tests if a decoration exists.
   */
  public final boolean has (Object key) {
    if(size()==0) return false;

    int index=hash(key)%capacity();
    HashtableData current=iData[index];

    while(current!=null) {
      if(current.iKey==key)return true;
      current=current.iNext;
    }
    return false;
  }


  /**
   * Sets the value of a decoration.
   */
  public final void set (Object key, Object value) throws
    InvalidAttributeException, CoreException {
    if(iSize >= iCapacity) { rehash(); }
    int index = hash(key)%capacity();

    HashtableData current = iData[index];
    while(current!=null) {
      if(current.iKey==key) {
	current.iElement=value;
	return;
      }
      current=current.iNext;
    }

    // if we're here, the key could not be found; insert at the head
    // of the list
    HashtableData toinsert = 
      new HashtableData(key, value, iData[index]);
    iData[index] = toinsert;
    iSize++;
  }


  /**
   * Gets the value of a decoration.
   */
  public final Object get (Object key) throws
    InvalidAttributeException, CoreException {
    if(size()==0) {
      throw new InvalidAttributeException("Empty Decorable\n"+
					  "\tDecorable "+this+"\n"+
					  "\tkey       "+key);
    }
    int index=hash(key)%capacity();
    HashtableData current=iData[index];
    while(current!=null) {
      if(current.iKey==key)return current.iElement;
      current=current.iNext;
    }
    throw new InvalidAttributeException("Attribute does not exist\n"+
					"\tDecorable "+this+"\n"+
					"\tkey       "+key);
  }


  public final ObjectIterator attributes () {
    Object[] toReturn = new Object[iSize];
    int index = 0;
    for (int i = 0; i < iCapacity; i++) {
      HashtableData current = iData[i];
      while (current != null) {
	toReturn[index++] = current.iKey;
	current = current.iNext;
      }
    }
    return new ArrayObjectIterator(toReturn);
  }
  
   
  /**
   * Gets the used data elements in this hashtable.
   */
  private final HashtableData[] data()
  {
    if(size()==0) return new HashtableData[0];
    HashtableData[] toRet=new HashtableData[size()];
    HashtableData current;
    int index=0;
    int curcap=capacity();
    for(int i=0;i<curcap;i++) {
      current=iData[i];
      while(current!=null) {
	toRet[index++]=current;
	current=current.iNext;
      }
    }
    return toRet;
  }

  
  /**
   * Gets the size.
   */
  protected final int size()
  {
    return iSize;
  }


  /**
   * Gets the capacity of this hashtable.  The capacity is cached to avoid
   * accessing iData.length many times.
   */
  protected final int capacity() {
    return iCapacity;
  }

  
  protected final void rehash() {
    if(iData==null) {
      initialAllocate();
    } else {
      // get the current state
      int curSize              = size();
      HashtableData curData [] = data();

      // build the new state
      iCapacity = PRIMES[iNextPrime++];
      iData     = new HashtableData[iCapacity];
      iSize     = 0;
      for(int i=0; i<curSize; i++) {
	set(curData[i].iKey,curData[i].iElement);
      }
    }
  }


  /**
   * Gets the hashcode for a particular object.  If the object is null, it
   * returns 0.  Uses System.identityHashCode (aka the address in memory).
   */
  protected final int hash(Object o)
  {
    //if(o==null)return 0;
    //what if hashcode is negative (7FFFFFFF?)
    return 0x7FFFFFFF & System.identityHashCode(o);
  }

  
  private final void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException
  {
    // output the size of the hashtable
    s.writeInt(size());
        
    if(size()==0) return;
        
    // output all the <key,element> pairs
    HashtableData data[] = data();

    for(int i=0; i<size(); i++) {
      s.writeObject(data[i].iKey);
      s.writeObject(data[i].iElement);
      /*            Object k,e ;
		    System.out.println("dumping "+k+" => "+e);
		    System.out.println("class is "+
                    ((e==null) ? "(nil)" : e.getClass().toString()));
		    s.writeObject(k);
		    s.writeObject(e);*/
    }
  }

  
  private final void readObject(java.io.ObjectInputStream s) 
    throws java.io.IOException,ClassNotFoundException
  {
    // read the actual size
    int size=s.readInt();

    if(size==0) {
      initEmpty();
      return;
    }
    else {
      for(int iNextPrime = 0; PRIMES[iNextPrime]<size; 
	  iNextPrime++);
      iCapacity= PRIMES[iNextPrime++];

      // allocate the table, fill it.
      iData=new HashtableData[iCapacity];
      for(int i=0;i<size;i++) {
	set(s.readObject(),s.readObject());
      }
    }
  }


  // nested class(es)
  
  private static class HashtableData {
    /**
     * The key.
     */
    Object iKey;

    /**
     * The element.
     */
    Object iElement;

    /**
     * The next node in the chain.
     */
    HashtableData iNext;

    /**
     * constructs a new node with no successor.
     */
    HashtableData(Object key, Object element)
    {
      this(key,element,null);
    }

    /**
     * Constructs a new node with a successor.
     */
    HashtableData(Object key, Object element, HashtableData next)
    {
      iKey=key;
      iElement=element;
      iNext=next;
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -