Class StorePageMap {/*** The table, resized as necessary. length MUST Always be a power of two. */private Entry [] table;/*** The number of key-value mappings contained in this identity hash map. */private int size;/*** The next size value at which to resize (capacity * load factor ). * @ serial */private int threshold;/*** Constructs an empty <tt> HashMap </tt> with the default initial capac Ity * (16) and the default load factor (0.75 ). */StorePageMap () {threshold = 12; table = new Entry [17];}/*** Returns the number of key-value mappings in this map. ** @ return the number of key-value mappings in this map. */final int size () {return size;}/*** Returns <tt> true </tt> if this map contains no key-value mappings. ** @ return <tt> true </tt> if this map contains no key-value mappi Ngs. */final boolean isEmpty () {return size = 0;}/*** Returns the first StorePage for the given key. */final TableStorePage get (long key) {int I = (int) (key % table. length); Entry e = table [I]; while (true) {if (e = null) return null; if (e. key = key) return e. value; e = e. next ;}}/*** Returns <tt> true </tt> if this map contains a StorePage for the * specified key. **/final boolean ContainsKey (long key) {return (get (key )! = Null);}/*** Add the StorePage with the key. multiple StorePage for the same key are valid. * The cause are multiple changes in one transaction. with SavePoints a rollback to a older * StorePage is valid. <p> * The latest StorePage is placed at first pos. */final TableStorePage add (long key, TableStorePage value) {int I = (int) (key % table. length); table [I] = new Entry (key, value, table [I]); I F (size ++> = threshold) resize (2 * table. length); return null;}/*** Rehashes the contents of this map into a new array with a * larger capacity. this method is called automatically when the * number of keys in this map reaches its threshold. ** If current capacity is MAXIMUM_CAPACITY, this method does not * resize the map, but sets threshold to Integer. MAX_VALUE. * This has the effect of p Reventing future CILS. ** @ param newCapacity the new capacity, MUST be a power of two; * must be greater than current capacity unless current * capacity is MAXIMUM_CAPACITY (in which case value * is irrelevant ). */final private void resize (int newCapacity) {Entry [] newTable = new Entry [newCapacity]; transfer (newTable); table = newTable; threshold = (int) (newCapacity * 0.75f);}/*** Transfer All entries from current table to newTable. */final private void transfer (Entry [] newTable) {Entry [] src = table; int newCapacity = newTable. length; for (int j = 0; j <src. length; j ++) {Entry e = src [j]; if (e! = Null) {src [j] = null; do {Entry next = e. next; e. next = null; int I = (int) (e. key % newCapacity); // The order for StorePages with the same key must not change // that we need to find the end of the link list. this is different to a typical HashTable if (newTable [I] = null) {newTable [I] = e;} else {Entry entry = newTable [I]; while (entry. next! = Null) entry = entry. next; entry. next = e;} e = next;} while (e! = Null) ;}}/ *** Removes the mapping for this key from this map if present. ** @ param key whose mapping is to be removed from the map. * @ return previous value associated with specified key, or <tt> null </tt> * if there was no mapping for key. A <tt> null </tt> return can * also indicate that the map previusly associated <tt> null </tt> * with the specified key. */final TableStorePage remove (Long key) {int I = (int) (key % table. length); Entry prev = table [I]; Entry e = prev; while (e! = Null) {Entry next = e. next; if (e. key = key) {size --; if (prev = e) table [I] = next; else prev. next = next; return e. value;} prev = e; e = next;} return null;}/*** Removes all mappings from this map. */final void clear () {Entry tab [] = table; for (int I = 0; I <tab. length; I ++) tab [I] = null; size = 0 ;} /*** Returns <tt> true </tt> if this map maps one or more keys to the * specified Value. ** @ param value whose presence in this map is to be tested. * @ return <tt> true </tt> if this map maps one or more keys to the * specified value. */final boolean containsValue (TableStorePage value) {Entry tab [] = table; for (int I = 0; I <tab. length; I ++) for (Entry e = tab [I]; e! = Null; e = e. next) if (value. equals (e. value) return true; return false;} static class Entry {final long key; final TableStorePage value; Entry next;/*** Create new entry. */Entry (long k, TableStorePage v, Entry n) {value = v; next = n; key = k ;}}}