/**
 * A growable array of hash slots that hold a little extra info
 * (AgeSlot). The slots are stored in an array, so that we don't do
 * lots and lots of little allocations.
 * 
 * Notice sloppy reuse of age field as an array link; wish I had a
 * union{}. This trick only works if you have an int field in your
 * *Slot structure.
 */
static class AgeArray {
	final static int freeList;
	AgeSlot[] aa;

	AgeArray(int initialSize) {
		grow(0, initialSize+1);
			// +1 accounts for the never-used freeList head (0) slot
	}

	add(int age, Object value) {
		// is there a free guy?
		int nextSlotI = aa[freeList].index;
		if (nextSlotI==0) {
			// if not, expand the array
			nextSlotI = grow(aa.length, aa.length*2);
		}
		// point free list pointer over the free guy
		aa[freeList].index = aa[nextSlotI].index;
		// assign the requested value
		aa[nextSlotI].index = nextSlotI;
		aa[nextSlotI].age = as.age;
		aa[nextSlotI].value = as.value;
	}

	private int grow(int oldsize, int newsize) {
		AgeSlot[] na = new AgeSlot[newsize];
		if (aa!=null) {
			System.arraycopy(aa, 0, na, 0, aa.length);
		}
		for (int i=oldsize; i<na.length; i++) {
			// link guys in na into a free list
			na[i].index = -(i+1);
		}

		// terminate the chain
		na[na.length-1].index = 0;
		aa=na;

		// return index of first guy in new chain
		return oldsize;
	}

	remove(int slotI) {
		// drop pointer to value data
		aa[slotI].value = null;
		// insert slot into free list chain
		aa[slotI].index = aa[freeList].index;
		aa[freeList] = -slotI;
	}

	int capacity() {
		return aa.capacity();
	}

	boolean containsValue(Object obj) {
		for (int i=0; i<aa.length; i++) {
			if ((aa[i].index>0)			// test if slot occupied
				&& obj.equals(aa[i].value)) {
				return true;
			}
		}
		return false;
	}
}

