/************************************************************************** * Copyright (c) 2001 by Punch Telematix. All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3. Neither the name of Punch Telematix nor the names of * * other contributors may be used to endorse or promote products * * derived from this software without specific prior written permission.* * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL PUNCH TELEMATIX OR OTHER CONTRIBUTORS BE LIABLE * * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ /** * $Id: IntHashtable.java,v 1.2 2006/04/18 13:00:29 cvs Exp $ */ package wonka.vm; public class IntHashtable { private final static float DEFAULT_LOADFACTOR = 0.75f; private final static int DEFAULT_CAPACITY = 101; private int capacity; private float loadFactor; private int occupancy; private int threshold; private int[] keys; private Object[] value; public IntHashtable() { this(DEFAULT_CAPACITY, DEFAULT_LOADFACTOR); } public IntHashtable(int initialCapacity) { this(initialCapacity, DEFAULT_LOADFACTOR); } public IntHashtable(int initialCapacity, float loadFactor) { if ( initialCapacity < 0 || loadFactor <= 0.0f ) throw new IllegalArgumentException("IntHashtable needs positive numbers"); this.capacity = (initialCapacity < 5 ? 5 :initialCapacity); this.keys = new int[capacity]; this.value = new Object[capacity]; this.loadFactor = (loadFactor > 1.0f ? DEFAULT_LOADFACTOR : loadFactor ); threshold = (int)(this.loadFactor * this.capacity); } public int size() { return this.occupancy; } public Object get(int key) { int cap = this.capacity; int i = key % cap; int[] k = keys; do { if(i < 0){ i += cap; } int ckey = k[i]; if(ckey == 0) { return null; } else if(key == ckey) { return this.value[i]; } else i--; } while(true); } public Object put(int key, Object newvalue) { int cap = this.capacity; int i = key % cap; int[] k = keys; do { if(i < 0){ i += cap; } int ckey = k[i]; if(ckey == 0) { k[i] = key; this.value[i] = newvalue; if(++this.occupancy >= threshold){ resize(); } return null; } else if(key == ckey) { Object oldvalue = this.value[i]; this.value[i] = newvalue; return oldvalue; } i--; } while(true); } public Object remove(int key) { int cap = this.capacity; int i = key % cap; int[] k = keys; do { if(i < 0){ i += cap; } int ckey = k[i]; if(ckey == 0) { return null; } else { if(key == ckey) { Object oldvalue = this.value[i]; deleteSlot(i); return oldvalue; } } --i; } while(true); } public void clear() { if (occupancy > 0) { keys = new int[capacity]; value = new Object[capacity]; occupancy = 0; } } private void resize() { int oldsize = this.capacity; int newsize = oldsize * 2 + 1; int[] oldkeys = this.keys; Object[] oldvalues = this.value; int[] newkeys = new int[newsize]; Object[] newvalues = new Object[newsize]; this.capacity = newsize; this.occupancy = 0; this.keys = newkeys; this.value = newvalues; this.threshold = (int) (loadFactor * newsize); for (int oldindex=0;oldindex<oldsize;++oldindex) { int key = oldkeys[oldindex]; if (key != 0) this.put(key,oldvalues[oldindex]); } } private void deleteSlot(int slotIndex) { int vacant, current, home, distance1, distance2; boolean happy; --occupancy; current = slotIndex; while(true) { // R1 keys[current] = 0; vacant = current; // R2 happy = true; while(happy) { current = current==0 ? capacity-1 : current-1; // R3 if (keys[current] == 0) { return; // normal termination } home = keys[current] % capacity; if(home < 0){ home += capacity; } distance1 = current<=home ? home - current : capacity + home - current; distance2 = current<=vacant ? vacant - current : capacity + vacant - current; happy = distance1<distance2; // back to R2 } // R4 keys[vacant] = keys[current]; value[vacant] = value[current]; // repeat from R1 ... } } }