Package anvil.java.util

Source Code of anvil.java.util.Hashlist$Iterator

/*
* $Id: Hashlist.java,v 1.3 2002/09/16 08:05:03 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.java.util;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

/**
* This class implements a hashlist, which maps keys to values. Any
* non-<code>null</code> object can be used as a key or as a value.
* <p>
* To successfully store and retrieve objects from a hashlist, the
* objects used as keys must implement the <code>hashCode</code>
* method and the <code>equals</code> method.
* <p>
* An instance of <code>Hashlist</code> has two parameters that
* affect its efficiency: its <i>capacity</i> and its <i>load
* factor</i>. The load factor should be between 0.0 and 1.0. When
* the number of entries in the hashlist exceeds the product of the
* load factor and the current capacity, the capacity is increased by
* calling the <code>rehash</code> method. Larger load factors use
* memory more efficiently, at the expense of larger expected time
* per lookup.
* <p>
* If many entries are to be made into a <code>Hashlist</code>,
* creating it with a sufficiently large capacity may allow the
* entries to be inserted more efficiently than letting it perform
* automatic rehashing as needed to grow the table.
* <p>
* This example creates a hashlist of numbers. It uses the names of
* the numbers as keys:
* <p><blockquote><pre>
*     Hashlist numbers = new Hashlist();
*     numbers.put("one", new Integer(1));
*     numbers.put("two", new Integer(2));
*     numbers.put("three", new Integer(3));
* </pre></blockquote>
* <p>
* To retrieve a number, use the following code:
* <p><blockquote><pre>
*     Integer n = (Integer)numbers.get("two");
*     if (n != null) {
*         System.out.println("two = " + n);
*     }
* </pre></blockquote>
*
* @author  Jani Lehtim�ki
* @version 1.41, 01/28/97
* @see     java.util.Hashlist#rehash()
*/
public class Hashlist
  extends Dictionary
  implements Map, Cloneable, java.io.Serializable
{

  /**
   * Hashlist collision list.
   */
  class Entry implements Holder {
    int hash;
    Object key;
    Object value;
    Entry next;
    Entry prevEntry;
    Entry nextEntry;
   
    public Object getKey()
    {
      return key;
    }
     
    public Object getValue()
    {
      return value;
    }
   
    public Object setValue(Object value)
    {
      Object oldvalue = this.value;
      this.value = value;
      return oldvalue;
    }

    public Object remove()
    {
      return Hashlist.this.remove(key);
    }
         
  }

  /**
   * A hashlist enumerator class.  This class should remain opaque
   * to the client. It will use the Enumeration interface.
   */
  class HashlistEnumerator implements BindingEnumeration {
    Entry current = null;
    boolean keys = false;

    HashlistEnumerator(boolean keys) {
      this.keys    = keys;
    }
     
    public boolean hasMoreElements() {
      Entry e = current;
      if (e != null) {
        return (e.nextEntry != null);
      } else {
        return (Hashlist.this.head != null);
      }
    }

    public Object nextElement() {
      Entry e = current;
      if (e == null) {
        current = (e = Hashlist.this.head);
      } else {
        current = (e = current.nextEntry);
      }
      if (e == null) {
        throw new NoSuchElementException("HashlistEnumerator");
      }
      return keys ? e.key : e.value;
    }

    public Object nextKey()
    {
      Entry e = current;
      if (e == null) {
        e = Hashlist.this.head;
      } else {
        e = e.nextEntry;
      }
      if (e == null) {
        throw new NoSuchElementException("HashlistEnumerator");
      }
      return e.key;
    }
   
  }


  /**
   * A hashlist iterator class. 
   */
  class Iterator implements HashlistIterator {
    int index;
    Entry current;
    Entry prev;
    Entry next;

    protected Iterator()
    {
      start();
    }


    public void start()
    {
      index = -1;
      current = null;
      prev = null;
      next = Hashlist.this.head;
    }


    public void end()
    {
      index = Hashlist.this.count;
      current = null;
      prev = Hashlist.this.tail;
      next = null;
    }


    public boolean hasPrevious()
    {
      return (prev != null);
    }


    public boolean hasCurrent()
    {
      return (current != null);
    }
     

    public boolean hasNext()
    {
      return (next != null);
    }


    public Object previous()
    {
      current = prev;
      if (current != null) {
        index--;
        prev = current.prevEntry;
        next = current.nextEntry;
        return current.value;
      } else {
        index = -1;
        prev = null;
        next = Hashlist.this.head;
        return null;
      }
    }
   
   
    public int previousIndex()
    {
      if (index > -1) {
        return index - 1;
      } else {
        return -1;
      }
    }


    public Object next()
    {
      current = next;
      if (current != null) {
        index++;
        prev = current.prevEntry;
        next = current.nextEntry;
        return current.value;
      } else {
        index = Hashlist.this.count;
        prev = Hashlist.this.tail;
        next = null;
        return null;
      }
    }
   

    public int nextIndex()
    {
      int max = Hashlist.this.count;
      if (index < max) {
        return index + 1;
      } else {
        return max;
      }
    }


    public int index()
    {
      return index;
    }


    public Object key()
    {
      return (current != null) ? current.key : null;
    }


    public Object value()
    {
      return (current != null) ? current.value : null;
    }
   

    public void add(Object value)
    {
    }


    public void remove()
    {
      /*if (current != null) {
        Hashlist.this.remove(current.key);
      }*/
    }
   
   
    public void set(Object value)
    {
      if (current != null) {
        current.setValue(value);
      }
    }

  }


  /**
   * The hash table data.
   */
  private transient Entry table[];

  /**
   * First item in the list
   */
  private transient Entry head = null;
 
  /**
   * Last item in the list
   */
  private transient Entry tail = null;

  /**
   * The total number of entries in the hash table.
   */
  private transient int count;

  /**
   * Next available integer index.
   */
  private int nextSequence = 0;
 
  /**
   * Rehashes the table when count exceeds this threshold.
   * @serial Integer
   */
  private int threshold;

  /**
   * The load factor for the hashlist.
   * @serial Float
   */
  private float loadFactor;

  /* use serialVersionUID from JDK 1.0.2 for interoperability */
  /*private static final long serialVersionUID = 1421746759512286392L;*/

  /**
   * Constructs a new, empty hashlist with the specified initial
   * capacity and the specified load factor.
   *
   * @param      initialCapacity   the initial capacity of the hashlist.
   * @param      loadFactor        a number between 0.0 and 1.0.
   * @exception  IllegalArgumentException  if the initial capacity is less
   *               than or equal to zero, or if the load factor is less than
   *               or equal to zero.
   */
  public Hashlist(int initialCapacity, float loadFactor) {
    if ((initialCapacity <= 0) || (loadFactor <= 0.0)) {
      throw new IllegalArgumentException();
    }
    this.loadFactor = loadFactor;
    table = new Entry[initialCapacity];
    threshold = (int)(initialCapacity * loadFactor);
  }

  /**
   * Constructs a new, empty hashlist with the specified initial capacity
   * and default load factor.
   *
   * @param   initialCapacity   the initial capacity of the hashlist.
   */
  public Hashlist(int initialCapacity) {
    this(initialCapacity, 0.75f);
  }

  /**
   * Constructs a new, empty hashlist with a default capacity and load
   * factor.
   *
   */
  public Hashlist() {
    this(101, 0.75f);
  }

  /**
   * Returns the number of keys in this hashlist.
   *
   * @return  the number of keys in this hashlist.
   */
  public int size() {
    return count;
  }

  /**
   * Tests if this hashlist maps no keys to values.
   *
   * @return  <code>true</code> if this hashlist maps no keys to values;
   *          <code>false</code> otherwise.
   */
  public boolean isEmpty() {
    return count == 0;
  }


  /**
   * Returns an enumeration of the keys in this hashlist.
   *
   * @return  an enumeration of the keys in this hashlist.
   * @see     java.util.Hashlist#elements()
   */
  public synchronized Enumeration keys() {
    return new HashlistEnumerator(true);
  }

  /**
   * Returns an enumeration of the values in this hashlist.
   * Use the Enumeration methods on the returned object to fetch the elements
   * sequentially.
   *
   * @return  an enumeration of the values in this hashlist.
   * @see     java.util.Hashlist#keys()
   */
  public synchronized Enumeration elements() {
    return new HashlistEnumerator(false);
  }


  public synchronized Collection values() {
    return null;
  }




  /**
   * Returns an enumeration of the values in this hashlist.
   * Use the Enumeration methods on the returned object to fetch the elements
   * sequentially.
   *
   * @return  an enumeration of the values in this hashlist.
   * @see     java.util.Hashlist#keys()
   */
  public synchronized BindingEnumeration keysAndElements() {
    return new HashlistEnumerator(false);
  }


 

  /**
   * Returns an iterator for hashlist.
   * User iterator to browse through the keys and values in the
   * insertion order.
   *
   * @return  an iterator for this hashlist.
   */
  public synchronized HashlistIterator hashlistIterator() {
    return new Iterator();
  }


  public synchronized ListIterator listIterator() {
    return new Iterator();
  }


  public synchronized Iterator iterator() {
    return new Iterator();
  }


  public Set keySet()
  {
    throw new RuntimeException("Not supported");
  }



  public Set entrySet()
  {
    throw new RuntimeException("Not supported");
  }


  public boolean containsValue(Object value)
  {
    return contains(value);
  }
 

  /**
   * Tests if some key maps into the specified value in this hashlist.
   * This operation is more expensive than the <code>containsKey</code>
   * method.
   *
   * @param      value   a value to search for.
   * @return     <code>true</code> if some key maps to the
   *             <code>value</code> argument in this hashlist;
   *             <code>false</code> otherwise.
   * @exception  NullPointerException  if the value is <code>null</code>.
   * @see        java.util.Hashlist#containsKey(java.lang.Object)
   */
  public synchronized boolean contains(Object value) {
    if (value == null) {
      throw new NullPointerException();
    }

    Entry tab[] = table;
    for (int i = tab.length ; i-- > 0 ;) {
      for (Entry e = tab[i] ; e != null ; e = e.next) {
        if (e.value.equals(value)) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Tests if the specified object is a key in this hashlist.
   *
   * @param   key   possible key.
   * @return  <code>true</code> if the specified object is a key in this
   *          hashlist; <code>false</code> otherwise.
   * @see     java.util.Hashlist#contains(java.lang.Object)
   */
  public synchronized boolean containsKey(Object key) {
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns the value to which the specified key is mapped in this hashlist.
   *
   * @param   key   a key in the hashlist.
   * @return  the value to which the key is mapped in this hashlist;
   *          <code>null</code> if the key is not mapped to any value in
   *          this hashlist.
   * @see     java.util.Hashlist#put(java.lang.Object, java.lang.Object)
   */
  public synchronized Object get(Object key) {
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        return e.value;
      }
    }
    return null;
  }


  /**
   * Returns the entry to which the specified key is mapped in this hashlist.
   *
   * @param   key   a key in the hashlist.
   * @return  the entry to which the key is mapped in this hashlist;
   *          <code>null</code> if the key is not mapped to any entry in
   *          this hashlist.
   * @see     java.util.Hashlist#put(java.lang.Object, java.lang.Object)
   */
  protected synchronized Entry getEntry(Object key) {
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        return e;
      }
    }
    return null;
  }



  /**
   * Returns the holder to which the specified key is mapped in this hashlist.
   *
   * @param   key   a key in the hashlist.
   * @return  the <code>Holder</code> to which the key is mapped in this hashlist;
   *          <code>null</code> if the key is not mapped to any entry in
   *          this hashlist.
   * @see     java.util.Hashlist#put(java.lang.Object, java.lang.Object)
   */
  public Holder getHolder(Object key)
  {
    return getEntry(key);
  }


  /**
   * Returns the Object to which the specified index (Integer) is mapped in this hashlist.
   *
   * @param   key   an index in the hashlist.
   * @return  the <code>Holder</code> to which the index is mapped in this hashlist;
   *          <code>null</code> if the index is not mapped to any entry in
   *          this hashlist.
   * @see     java.util.Hashlist#put(java.lang.Object, java.lang.Object)
   */
  public Object get(int index)
  {
    return get(new Integer(index));
  }
 


  /**
   * Returns the <code>Holder</code> to which the specified index (Integer)
   * is mapped in this hashlist.
   *
   * @param   key   an index in the hashlist.
   * @return  the <code>Holder</code> to which the index is mapped in this hashlist;
   *          <code>null</code> if the index is not mapped to any <code>Holder</code> in
   *          this hashlist.
   * @see     java.util.Hashlist#put(java.lang.Object, java.lang.Object)
   */
  public Holder getHolder(int index)
  {
    return getEntry(new Integer(index));
  }


  /**
   * Rehashes the contents of the hashlist into a hashlist with a
   * larger capacity. This method is called automatically when the
   * number of keys in the hashlist exceeds this hashlist's capacity
   * and load factor.
   *
   */
  protected void rehash() {
    int oldCapacity = table.length;
    Entry oldTable[] = table;

    int newCapacity = oldCapacity * 2 + 1;
    Entry newTable[] = new Entry[newCapacity];

    threshold = (int)(newCapacity * loadFactor);
    table = newTable;

    //System.out.println("rehash old=" + oldCapacity + ", new=" + newCapacity + ", thresh=" + threshold + ", count=" + count);

    for (int i = oldCapacity ; i-- > 0 ;) {
      for (Entry old = oldTable[i] ; old != null ; ) {
        Entry e = old;
        old = old.next;

        int index = (e.hash & 0x7FFFFFFF) % newCapacity;
        e.next = newTable[index];
        newTable[index] = e;
      }
    }
  }


  public void putAll(Map map) {
    Set keys = map.keySet();
    java.util.Iterator i = keys.iterator();
    while(i.hasNext()) {
      Object key = i.next();
      Object value = map.get(key);
      put(key, value);
    }
  }


  /**
   * Maps the specified <code>key</code> to the specified
   * <code>value</code> in this hashlist. Neither the key nor the
   * value can be <code>null</code>.
   * <p>
   * The value can be retrieved by calling the <code>get</code> method
   * with a key that is equal to the original key.
   *
   * @param      key     the hashlist key.
   * @param      value   the value.
   * @return     the previous value of the specified key in this hashlist,
   *             or <code>null</code> if it did not have one.
   * @exception  NullPointerException  if the key or value is
   *               <code>null</code>.
   * @see     java.util.Hashlist#get(java.lang.Object)
   */
  public synchronized Object put(Object key, Object value) {
 
    // Make sure the value is not null
   
    if (key == null || value == null) {
      throw new NullPointerException();
    }

    // Makes sure the key is not already in the hashlist.
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        Object old = e.value;
        e.value = value;
        return old;
      }
    }

    if (count >= threshold) {
      // Rehash the table if the threshold is exceeded
      rehash();
      return put(key, value);
    }
   
    if (key instanceof Integer) {
      int i = ((Integer)key).intValue();
      if (i >= nextSequence) {
        nextSequence = i+1;
      }
    }
   
    // Creates the new entry.
    Entry e = new Entry();
    e.hash = hash;
    e.key = key;
    e.value = value;
    e.next = tab[index];
    e.prevEntry = tail;
    e.nextEntry = null;
    tab[index] = e;
    count++;

    if (head == null) {
      head = e;
    }
    if (tail != null) {
      tail.nextEntry = e;
    }
    tail = e;

    return null;
  }


  protected synchronized Object putBefore(Object key, Object value, Entry before) {
 
    // Make sure the value is not null
   
    if (key == null || value == null) {
      throw new NullPointerException();
    }

    // Makes sure the key is not already in the hashlist.
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        Object old = e.value;
        e.value = value;
        return old;
      }
    }

    if (count >= threshold) {
      // Rehash the table if the threshold is exceeded
      rehash();
      return putBefore(key, value, before);
    }
   
    if (key instanceof Integer) {
      int i = ((Integer)key).intValue();
      if (i >= nextSequence) {
        nextSequence = i+1;
      }
    }
   
    // Creates the new entry.
    Entry e = new Entry();
    e.hash = hash;
    e.key = key;
    e.value = value;
    e.next = tab[index];
    tab[index] = e;
    count++;

   
    if (before == null) {
      before = head;
    }
    if (before == null) {
      e.prevEntry = null;
      e.nextEntry = null;
      head = tail = e;
    } else if (before == head) {
      e.prevEntry = null;
      e.nextEntry = before;
      before.prevEntry = e;
      head = e;
    } else {
      Entry prev = before.prevEntry;
      e.prevEntry = prev;
      // previous if guarantees that (prev != null)
      prev.nextEntry = e;
      e.nextEntry = before;
      before.prevEntry = e;
    }
   
    return null;
  }


  /**
   * Maps the specified <code>key</code> to the specified
   * <code>value</code> in this hashlist. Neither the key nor the
   * value can be <code>null</code>.
   * <p>
   * The value can be retrieved by calling the <code>get</code> method
   * with a key that is equal to the original key.
   *
   * @param      key     the hashlist key.
   * @param      value   the value.
   * @return     Holder where the key and value were stored
   * @exception  NullPointerException  if the key or value is
   *               <code>null</code>.
   * @see     java.util.Hashlist#getHolder(java.lang.Object)
   */
  public synchronized Holder putHolder(Object key, Object value) {
 
    // Make sure the value is not null
   
    if (key == null || value == null) {
      throw new NullPointerException();
    }

    // Makes sure the key is not already in the hashlist.
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        e.value = value;
        return e;
      }
    }

    if (count >= threshold) {
      // Rehash the table if the threshold is exceeded
      rehash();
      return putHolder(key, value);
    }

    if (key instanceof Integer) {
      int i = ((Integer)key).intValue();
      if (i >= nextSequence) {
        nextSequence = i+1;
      }
    }
   
    // Creates the new entry.
    Entry e = new Entry();
    e.hash = hash;
    e.key = key;
    e.value = value;
    e.next = tab[index];
    e.prevEntry = tail;
    e.nextEntry = null;
    tab[index] = e;
    count++;

    if (head == null) {
      head = e;
    }
    if (tail != null) {
      tail.nextEntry = e;
    }
    tail = e;

    return e;
  }


  /**
   * Maps the specified <code>index</code> to the specified
   * <code>value</code> in this hashlist. Neither the index nor the
   * value can be <code>null</code>.
   * <p>
   * The value can be retrieved by calling the <code>get</code> method
   * with a key that is equal to the original key.
   *
   * @param      index   the hashlist index.
   * @param      value   the value.
   * @return     the previous value of the specified key in this hashlist,
   *             or <code>null</code> if it did not have one.
   * @exception  NullPointerException  if the index or value is
   *               <code>null</code>.
   * @see     java.util.Hashlist#get(int)
   */
  public Object put(int index, Object value)
  {
    return put(new Integer(index), value);
  }


  /**
   * Maps the specified <code>index</code> to the specified
   * <code>value</code> in this hashlist. Neither the index nor the
   * value can be <code>null</code>.
   * <p>
   * The value can be retrieved by calling the <code>get</code> method
   * with a key that is equal to the original key.
   *
   * @param      index   the hashlist index.
   * @param      value   the value.
   * @return     Holder where key and value were stored
   * @exception  NullPointerException  if the index or value is
   *               <code>null</code>.
   * @see     java.util.Hashlist#get(java.lang.Integer)
   */
  public Holder putHolder(int index, Object value)
  {
    return putHolder(new Integer(index), value);
  }


  protected Object putBefore(int index, Object value, Entry entry)
  {
    return putBefore(new Integer(index), value, entry);
  }


  protected Object putBefore(Object value, Entry entry)
  {
    return putBefore(new Integer(nextSequence), value, entry);
  }


  /**
   * Removes the key (and its corresponding value) from this
   * hashlist. This method does nothing if the key is not in the hashlist.
   *
   * @param   key   the key that needs to be removed.
   * @return  the value to which the key had been mapped in this hashlist,
   *          or <code>null</code> if the key did not have a mapping.
   */
  public synchronized Object remove(Object key) {
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
     
        if (prev != null) {
          prev.next = e.next;
        } else {
          tab[index] = e.next;
        }
       
        if (head == e) {
          head = e.nextEntry;
        }
        if (tail == e) {
          tail = e.prevEntry;
        }
       
        if (e.nextEntry != null) {
          e.nextEntry.prevEntry = e.prevEntry;
        }
        if (e.prevEntry != null) {
          e.prevEntry.nextEntry = e.nextEntry;
        }
       
        count--;
        return e.value;
      }
    }
    return null;
  }


  /**
   * Clears this hashlist so that it contains no keys.
   *
   */
  public synchronized void clear() {
    Entry tab[] = table;
    for (int index = tab.length; --index >= 0; ) {
      tab[index] = null;
    }
    head = null;
    tail = null;
    count = 0;
    nextSequence = 0;
  }


  /**
   * Creates a shallow copy of this hashlist. The keys and values
   * themselves are not cloned.
   * This is a rather expensive operation.
   *
   * @return  a clone of the hashlist.
   */
  public synchronized Object clone() {
    Entry p = head;
    Hashlist t = new Hashlist(table.length, loadFactor);
    while(p != null) {
      t.put(p.key, p.value);
      p = p.nextEntry;
    }
    return t;
  }


  /**
   * Returns a rather long string representation of this hashlist.
   *
   * @return  a string representation of this hashlist.
   */
  public synchronized String toString() {
    StringBuffer buf = new StringBuffer();
    Entry e = head;
    boolean first = true;
    int max = size() - 1;
   
    buf.append('[');

    while(e != null) {
      if (first) {
        first = false;
      } else {
        buf.append(',');
        buf.append(' ');
      }
      buf.append(e.key.toString());
      buf.append('=');
      buf.append(e.value.toString());
      e = e.nextEntry;
    }

    buf.append(']');
   
    return buf.toString();
  }


  /**
   * Gets the next available integer slot.
   *
   * @return Sequence
   */
  public synchronized int getNextSequence()
  {
    return nextSequence;
  }
 
 
  /**
   * List operations
   */
  

  protected Entry entryAt(int index)
  {
    if ((index < 0) || (index >= count)) {
      return null;
    } else if (index < count/2) {
      Entry e = head;
      while(e != null) {
        if ((index--) <= 0) {
          return e;
        }
        e = e.nextEntry;
      }
    } else {
      index = count - index;
      Entry e = tail;
      while(e != null) {
        if ((--index) <= 0) {
          return e;
        }
        e = e.prevEntry;
      }
    }
    return null;
  }


  public synchronized int indexOf(Object key)
  {
    Entry start = getEntry(key);
    if (start != null) {
      Entry end = start;
      int pos = 0;
      for(;;) {
        pos ++;
        start = start.prevEntry;
        end = end.prevEntry;
        if (start == null) {
          return pos - 1;
        } else if (end == null) {
          return count - pos;
        }
      }
    } else {
      return -1;
    }
  }
 

  public synchronized Holder holderAt(int index)
  {
    return entryAt(index);
  }
 

  public synchronized Object keyAt(int index)
  {
    Entry e = entryAt(index);
    return (e != null) ? e.key : null;
  }


  public synchronized Object elementAt(int index)
  {
    Entry e = entryAt(index);
    return (e != null) ? e.value : null;
  }


  public synchronized boolean addAll(Collection c)
  {
    return true;
  }
 

  public synchronized Hashlist add(Object value)
  {
    put(nextSequence, value);
    return this;
  }


  public Hashlist add(int index, Object value)
  {
    put(index, value);
    return this;
  }


  public Hashlist add(Object key, Object value)
  {
    put(key, value);
    return this;
  }
 

  public synchronized Hashlist insert(Object value)
  {
    putBefore(new Integer(nextSequence), value, this.head);
    return this;
  }


  public synchronized Hashlist insert(Object key, Object value)
  {
    putBefore(key, value, this.head);
    return this;
  }


  public synchronized Hashlist insertAt(int index, Object key, Object value)
  {
    if (index >= count) {
      add(key, value);
    } else {
      putBefore(key, value, entryAt(index));
    }
    return this;
  }

 
  public synchronized Hashlist insertAt(int index, Object value)
  {
    if (index >= count) {
      add(value);
    } else {
      putBefore(new Integer(nextSequence), value, entryAt(index));
    }
    return this;
  }


  public synchronized Object setAt(int index, Object value)
  {
    Entry e = entryAt(index);
    if (e != null) {
      Object old = e.value;
      e.value = value;
      return old;
    } else {
      return null;
    }
  }


  public synchronized Object removeAt(int index)
  {
    Entry e = entryAt(index);
    if (e != null) {
      return remove(e.key);
    } else {
      return null;
    }
  }


  public synchronized Holder previousOf(Object index)
  {
    Entry e = getEntry(index);
    if (e != null) {   
      e = e.prevEntry;
    }
    return e;
  }


  public synchronized Holder nextOf(Object index)
  {
    Entry e = getEntry(index);
    if (e != null) {   
      e = e.nextEntry;
    }
    return e;
  }


  public synchronized Object[] toArray()
  {
    Object[] array = new Object[count];
    Entry p = head;
    int i = 0;
    while(p != null) {
      array[i++] = p.value;
      p = p.nextEntry;
    }
    return array;
  }


  public synchronized Object[] toArray(Class ofClass)
  {
    Object[] array = (Object [])
      java.lang.reflect.Array.newInstance(ofClass, count);
    Entry p = head;
    int i = 0;
    while(p != null) {
      array[i++] = p.value;
      p = p.nextEntry;
    }
    return array;   
  }



  public synchronized Hashlist slice(int start, int length)
  {
    boolean forward = true;
    if (length < 0) {
      length = -length;
      start -= (length - 1);
      forward = false;
    }
    if (start < 0) {
      length -= -start;
      if (length < 0) {
        length = 0;
      }
      start = 0;
    } else if (start > count) {
      start = count;
    }
    if (start + length > count) {
      length = count - start;
   
    if (length > 0) {
      Hashlist slice = new Hashlist(4 * length / 3);
      if (forward) {
        Entry p = entryAt(start);
        while(length-- > 0) {
          slice.put(p.key, p.value);
          p = p.nextEntry;
        }
      } else {
        Entry p = entryAt(start + length - 1);
        while(length-- > 0) {
          slice.put(p.key, p.value);
          p = p.prevEntry;
        }
      }
      return slice;
    } else {
      return null;
    }
  }



  public synchronized Hashlist cut(int start, int length)
  {
    if (length < 0) {
      length = -length;
      start -= (length - 1);
    }
    if (start < 0) {
      length -= -start;
      if (length < 0) {
        length = 0;
      }
      start = 0;
    } else if (start > count) {
      start = count;
    }
    if (start + length > count) {
      length = count - start;
   
   
    Entry p = entryAt(start);
    Entry q;
    while(length-- > 0) {
      q = p.nextEntry;
      remove(p.key);
      p = q;
    }

    return this;
  }



  public synchronized Hashlist insert(int start, int length, Hashlist array)
  {
    if (length < 0) {
      length = -length;
      start -= (length -1);
    }
    if (start < 0) {
      length -= -start;
      if (length < 0) {
        length = 0;
      }
      start = 0;
    } else if (start > count) {
      start = count;
    }
    if (start + length > count) {
      length = count - start;
   
   
    Entry p = entryAt(start);
    Entry q;
    while(length-- > 0) {
      q = p.nextEntry;
      remove(p.key);
      p = q;
    }
    if (p == null) {
      q = array.head;
      while(q != null) {
        add(q.value);
        q = q.nextEntry;
      }
    } else {
      q = array.tail;
      while(q != null) {
        putBefore(q.value, p);
        q = q.prevEntry;
      }
    }
    return this;
  }


  public synchronized Hashlist union(Hashlist array)
  {
    Entry p = array.head;
    while(p != null) {
      if (!containsKey(p.key)) {
        put(p.key, p.value);
      }
      p = p.nextEntry;
    }
    return this;
  }


  public synchronized Hashlist intersect(Hashlist array)
  {
    Entry p = head;
    while(p != null) {
      if (!array.containsKey(p.key)) {
        remove(p.key);
      }
      p = p.nextEntry;
    }
    return this;
  }


  public synchronized Hashlist sort(Comparator comparator, boolean ascending)
  {
    if (count == 2) {
      if (comparator.compare(head, tail) > 0) {
        Entry p = head;
        head = tail;
        tail = p;
        head.nextEntry = tail;
        head.prevEntry = null;
        tail.nextEntry = null;
        tail.prevEntry = head;
      }
    } else if (count > 2) {
      int i = 0;
      int n = count;
      Entry[] array = new Entry[n];
      if (ascending) {
        Entry p = head;
        while(p != null) {
          array[i++] = p;
          p = p.nextEntry;
        }
      } else {
        Entry p = tail;
        while(p != null) {
          array[i++] = p;
          p = p.prevEntry;
        }
      }
      java.util.Arrays.sort(array, comparator);
      Entry p;
      n--;
      for(i=0; i<=n; i++) {
        p = array[i];
        p.prevEntry = (i>0) ? array[i-1] : null;
        p.nextEntry = (i<n) ? array[i+1] : null;
      }
      head = array[0];
      tail = array[n];
    }
    return this;
  }

  /**
   * WriteObject is called to save the state of the hashlist to a stream.
   * Only the keys and values are serialized since the hash values may be
   * different when the contents are restored.
   * iterate over the contents and write out the keys and values.
   */
  private synchronized void writeObject(java.io.ObjectOutputStream s)
    throws IOException
  {
    // Write out the length, threshold, loadfactor
    s.defaultWriteObject();

    // Write out length, count of elements and then the key/value objects
    s.writeInt(table.length);
    s.writeInt(count);
    Entry entry = head;
    while (entry != null) {
      s.writeObject(entry.key);
      s.writeObject(entry.value);
      entry = entry.nextEntry;
    }
  }

  /**
   * readObject is called to restore the state of the hashlist from
   * a stream.  Only the keys and values are serialized since the
   * hash values may be different when the contents are restored.
   * Read count elements and insert into the hashlist.
   */
  private synchronized void readObject(java.io.ObjectInputStream s)
     throws IOException, ClassNotFoundException
  {
    // Read in the length, threshold, and loadfactor
    s.defaultReadObject();

    // Read the original length of the array and number of elements
    int origlength = s.readInt();
    int elements = s.readInt();

    // Compute new size with a bit of room 5% to grow but
    // No larger than the original size.  Make the length
    // odd if it's large enough, this helps distribute the entries.
    // Guard against the length ending up zero, that's not valid.
    int length = (int)(elements * loadFactor) + (elements / 20) + 3;
    if (length > elements && (length & 1) == 0)
      length--;
    if (origlength > 0 && length > origlength)
      length = origlength;

    table = new Entry[length];
    count = 0;

    // Read the number of elements and then all the key/value objects
    for (; elements > 0; elements--) {
      Object key = s.readObject();
      Object value = s.readObject();
      put(key, value);
    }
  }





}
TOP

Related Classes of anvil.java.util.Hashlist$Iterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.