/** * Copyright 2010 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * */ package org.drools.core.util; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class ObjectHashMap extends AbstractHashTable implements Externalizable { private static final long serialVersionUID = 510l; public ObjectHashMap() { this( 16, 0.75f ); } public ObjectHashMap(final int capacity, final float loadFactor) { super( capacity, loadFactor ); } public ObjectHashMap(final Entry[] table) { super( 0.75f, table); } public ObjectHashMap(final float loadFactor, final Entry[] table) { super(loadFactor, table); } public Object put(final Object key, final Object value) { return put( key, value, true ); } public void clear() { this.table = new Entry[Math.min( this.table.length, 16 )]; this.threshold = (int) (this.table.length * this.loadFactor); size = 0; } public Object put(final Object key, final Object value, final boolean checkExists) { final int hashCode = this.comparator.hashCodeOf( key ); final int index = indexOf( hashCode, this.table.length ); // scan the linked entries to see if it exists if ( checkExists ) { ObjectEntry current = (ObjectEntry) this.table[index]; while ( current != null ) { if ( hashCode == current.hashCode && this.comparator.equal( key, current.key ) ) { final Object oldValue = current.value; current.value = value; return oldValue; } current = (ObjectEntry) current.getNext(); } } // We aren't checking the key exists, or it didn't find the key final ObjectEntry entry = new ObjectEntry( key, value, hashCode ); entry.next = this.table[index]; this.table[index] = entry; if ( this.size++ >= this.threshold ) { resize( 2 * this.table.length ); } return null; } public Object get(final Object key) { final int hashCode = this.comparator.hashCodeOf( key ); final int index = indexOf( hashCode, this.table.length ); ObjectEntry current = (ObjectEntry) this.table[index]; while ( current != null ) { if ( hashCode == current.hashCode && this.comparator.equal( key, current.key ) ) { return current.value; } current = (ObjectEntry) current.getNext(); } return null; } public Object remove(final Object key) { final int hashCode = this.comparator.hashCodeOf( key ); final int index = indexOf( hashCode, this.table.length ); ObjectEntry previous = (ObjectEntry) this.table[index]; ObjectEntry current = previous; while ( current != null ) { final ObjectEntry next = (ObjectEntry) current.getNext(); if ( hashCode == current.hashCode && this.comparator.equal( key, current.key ) ) { if ( previous == current ) { this.table[index] = next; } else { previous.setNext( next ); } current.setNext( null ); this.size--; return current.value; } previous = current; current = next; } return null; } public Entry getBucket(final Object object) { final int hashCode = this.comparator.hashCodeOf( object ); final int index = indexOf( hashCode, this.table.length ); return this.table[index]; } public static class ObjectEntry implements Entry, Externalizable { private static final long serialVersionUID = 510l; private Object key; private Object value; private int hashCode; private Entry next; public ObjectEntry() { } public ObjectEntry(final Object key, final Object value, final int hashCode) { this.key = key; this.value = value; this.hashCode = hashCode; } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { key = in.readObject(); value = in.readObject(); hashCode = in.readInt(); next = (Entry)in.readObject(); } public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(key); out.writeObject(value); out.writeInt(hashCode); out.writeObject(next); } public Object getValue() { return this.value; } public Object getKey() { return this.key; } public Entry getNext() { return this.next; } public void setNext(final Entry next) { this.next = next; } public int hashCode() { return this.hashCode; } public boolean equals(final Object object) { if ( object == this ) { return true; } // assumes we never have null or wrong class final ObjectEntry other = (ObjectEntry) object; return this.key.equals( other.key ) && this.value.equals( other.value ); } } }