/* * Copyright (c) 2002,2009 Declarative Engineering LLC. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Declarative Engineering LLC * verson 1 which accompanies this distribution, and is available at * http://declarativeengineering.com/legal/DE_Developer_License_v1.txt */ package com.common.util.optimized; import com.common.util.*; import com.common.comparison.*; /** * This collection maps a value by a key. */ public class IntObjectHashMap extends Map implements IIntObjectHashMap { private int[] keys = null; private int keyCount = 0; /** * The Entry wrappers the key/value pair. */ protected static class Entry extends BasicEntry { public int key = 0; public Object value = null; protected Entry() { super(); }//Entry()// public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException { super.readExternal(in); key = in.readInt(); value = in.readObject(); }//readExternal()// public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException { super.writeExternal(out); out.writeInt(key); out.writeObject(value); }//writeExternal()// public int createKeyHash() { return key; }//createKeyHash()// public String toString() { return super.toString() + "\r\n\thash: " + hash + "\r\n\tkey: " + key + "\r\n\tvalue: " + (value != null ? value.toString() : "null") + (next != null ? ("\r\n" + next.toString()) : ""); }//toString()// }//Entry// public static class KeyIterator extends Iterator implements IIntIterator { public KeyIterator(IntObjectHashMap hashMap) { super(hashMap); }//KeyIterator()// public int next() { return ((Entry) nextEntry()).key; }//next()// public int previous() { return ((Entry) previousEntry()).key; }//previous()// }//KeyIterator// public static class ValueIterator extends Iterator implements IReversableIterator { public ValueIterator(IntObjectHashMap hashMap) { super(hashMap); }//ValueIterator()// public Object next() { return ((Entry) nextEntry()).value; }//next()// public Object previous() { return ((Entry) previousEntry()).value; }//previous()// }//ValueIterator// /** * IntObjectHashMap constructor. */ protected IntObjectHashMap() { this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, DEFAULT_VALUE_COMPARATOR); }//IntObjectHashMap()// /** * IntObjectHashMap constructor. * @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException. */ public IntObjectHashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_VALUE_COMPARATOR); }//IntObjectHashMap()// /** * IntObjectHashMap constructor. * @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException. * @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException. */ public IntObjectHashMap(int initialCapacity, float loadFactor) { this(initialCapacity, loadFactor, DEFAULT_VALUE_COMPARATOR); }//IntObjectHashMap()// /** * IntObjectHashMap constructor. * @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException. * @param loadFactor The ratio that determines when the map should increase capacity. This value should be greater than 0.0 and any other value will cause an IllegalArgumentException. * @param valueComparator The comparator used to compare value objects. */ public IntObjectHashMap(int initialCapacity, float loadFactor, IComparator valueComparator) { super(initialCapacity, loadFactor, null, valueComparator); }//IntObjectHashMap()// /** * IntObjectHashMap constructor. * @param initialCapacity The initial capacity of the map. This value should be between 1..+N, a value of zero will be silently modified to a value of one. Any other value will cause an IllegalArgumentException. * @param valueComparator The comparator used to compare value objects. */ public IntObjectHashMap(int initialCapacity, IComparator valueComparator) { this(initialCapacity, DEFAULT_LOAD_FACTOR, valueComparator); }//IntObjectHashMap()// /** * @see IIntObjectHashMap.containsKey(int) */ public boolean containsKey(int key) { return get(key) != null; }//containsKey()// /** * Will create an entry object of the specific type used by this map. * @return BasicEntry An entry object that can be filled and passed to the addEntry method. */ protected IBasicEntry createEntry() { return new Entry(); }//createEntry()// /** * Gets the first available value in the map. * @return The first accessable value in the map. */ public Object getFirst() { IBasicEntry[] entries = getEntries(); for(int index = 0; index < entries.length; index++) { for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) { if(entry != null) { return entry.value; }//if// }//for// }//for// return null; }//getFirst()// /** * @see IIntObjectHashMap.get(int) */ public Object get(int key) { IBasicEntry[] entries = getEntries(); int hash = key; int index = (hash & 0x7FFFFFFF) % entries.length; for(Entry entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) { if((entry.hash == hash) && (entry.key == key)) { return entry.value; }//if// }//for// return null; }//get()// /** * This method will get the key at the given index. *
NOTE: This method is intended for use by the iterators and it is not advisable to use this method else where. * @param index The index in the list of keys. * @return The key at the given index. */ public int getKey(int index) { if(keys == null) { refreshKeys(); }//if// return keys[index]; }//get()// /** * This will invalidate the collection of keys. * This should occur when a value is added/removed/changed in a way that invalidates the collection of keys. */ protected void invalidateKeys() { keys = null; keyCount = 0; }//invalidateKeys()// /** * @see IIntObjectHashMap.keyIterator() */ public IIntIterator keyIterator() { return new KeyIterator(this); }//keyIterator()// /** * @see IIntObjectHashMap.put(int, Object) */ public Object put(int key, Object value) { //Verify that the collection can be modified.// verifyIsChangeable(); if(value == null) { //Remove the key if it exists because you cannot associate a key with a null value.// return remove(key); }//if// else { IBasicEntry[] entries = getEntries(); int hash = key; int index = (hash & 0x7FFFFFFF) % entries.length; Entry entry = null; //Try to locate an existing value.// for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) { if((entry.hash == hash) && (entry.key == key)) { Object oldValue = entry.value; entry.value = value; return oldValue; }//if// }//for// //Determine if we need to re-hash.// if(resize(getSize() + 1)) { entries = getEntries(); //Recalculate the insertion index if the map resized.// index = (hash & 0x7FFFFFFF) % entries.length; }//if// //Create and add the new entry.// entry = (Entry) createEntry(); entry.hash = hash; entry.key = key; entry.value = value; addEntry(index, entry); if(keys != null) { //Just add the key instead of invalidating the keys collection.// if(keyCount == keys.length) { int[] temp = new int[keys.length < 50 ? keys.length << 1 : keys.length + 100]; System.arraycopy(keys, 0, temp, 0, keys.length); keys = temp; keys[keyCount++] = key; }//if// keys[keyCount++] = key; keyCount++; }//if// return null; }//else// }//put()// /** * Will recreate the collection of keys. */ protected void refreshKeys() { IBasicEntry[] entries = getEntries(); int index; Entry entry; keys = new int[getSize() + 10]; for(index = 0; index < entries.length; index++) { for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) { keys[index] = entry.key; keyCount++; }//for// }//for// }//refreshKeys()// /** * Will optimize the collection of Entry objects to improve access time. * @param arrayLength int The new length of the entry array. */ protected void rehash(int arrayLength) { super.rehash(arrayLength); //Invalidate the list of keys.// invalidateKeys(); }//rehash()// /** * @see IIntObjectHashMap.remove(int) */ public Object remove(int key) { IBasicEntry[] entries = getEntries(); int hash = key; int index = (hash & 0x7FFFFFFF) % entries.length; Entry previousEntry = null; Entry entry = null; Object retVal = null; //Verify that the collection can be modified.// verifyIsChangeable(); //Iterate through the entries stored at the key's hash location and remove the given key.// for(entry = (Entry) entries[index]; entry != null; entry = (Entry) entry.next) { if((entry.hash == hash) && (entry.key == key)) { //Save the removed value.// retVal = entry.value; //Remove the entry from the map.// removeEntry(index, previousEntry); //Could find the key in the collection and remove it, but that may take to long.// invalidateKeys(); //Break from the loop so we can exit.// break; }//if// previousEntry = entry; }//for// return retVal; }//remove()// /** * @see IIntObjectHashMap.removeAll() */ public boolean removeAll() { //Verify that the collection can be modified.// verifyIsChangeable(); invalidateKeys(); removeAllEntries(); return true; }//removeAll()// /** * @see IIntObjectHashMap.valueIterator() */ public IIterator valueIterator() { return new ValueIterator(this); }//valueIterator()// }//IntObjectHashMap//