/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.vm.objects; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @author epr */ public class BootableHashMap<K, V> extends VmSystemObject implements Map<K, V> { private HashMap<K, V> mapCache; private Entry<K, V>[] entryArray; private int hashCode; private transient boolean locked; /** * Constructs an empty HashMap. * @see java.util.HashMap#HashMap() */ public BootableHashMap() { this.hashCode = super.hashCode(); } /** * Constructs an empty HashMap. * @see java.util.HashMap#HashMap(int) * * @param initialCapacity */ public BootableHashMap(int initialCapacity) { mapCache = new HashMap<K, V>(initialCapacity); this.hashCode = mapCache.hashCode(); } /** * @return int * @see java.lang.Object#hashCode() */ public int hashCode() { if (mapCache != null) { return getMapCache().hashCode(); } else { return hashCode; } } /** * @return String * @see java.lang.Object#toString() */ public String toString() { if (mapCache != null) { return getMapCache().toString(); } else { return super.toString(); } } /** * @return The collection of values */ public Collection<V> values() { return getMapCache().values(); } /** * @return The set of keys */ public Set<K> keySet() { return getMapCache().keySet(); } /** * @param key * @return The object for the given key, or null if the given key is not found. */ public V get(Object key) { return getMapCache().get(key); } /** * */ public void clear() { getMapCache().clear(); } /** * @return The number of elements */ public int size() { return getMapCache().size(); } /** * @param key * @param value * @return Object */ public V put(K key, V value) { return getMapCache().put(key, value); } /** * @param m */ public void putAll(Map<? extends K, ? extends V> m) { getMapCache().putAll(m); } /** * @return The set of entries */ public Set<Map.Entry<K, V>> entrySet() { return getMapCache().entrySet(); } /** * @param key * @return True if the key is contained, false otherwise */ public boolean containsKey(Object key) { return getMapCache().containsKey(key); } /** * @return True if this map is empty, false otherwise */ public boolean isEmpty() { return getMapCache().isEmpty(); } /** * @param obj * @return boolean * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { return getMapCache().equals(obj); } /** * @param o * @return Object */ public V remove(Object o) { return getMapCache().remove(o); } /** * @param value * @return True if the given value is contained, false otherwise */ public boolean containsValue(Object value) { return getMapCache().containsValue(value); } static final class Entry<eK, eV> extends VmSystemObject { private final eK key; private final eV value; public Entry(Map.Entry<eK, eV> entry) { this.key = entry.getKey(); this.value = entry.getValue(); } /** * Gets the key * * @return Object */ public eK getKey() { return key; } /** * Gets the value * * @return Object */ public eV getValue() { return value; } } /** * Gets the hashmap * * @return */ private final HashMap<K, V> getMapCache() { if (locked) { throw new RuntimeException("Cannot change a locked BootableHashMap"); } if (mapCache == null) { if (entryArray != null) { final int max = entryArray.length; mapCache = new HashMap<K, V>(max); for (int i = 0; i < max; i++) { final Entry<K, V> e = entryArray[i]; mapCache.put(e.getKey(), e.getValue()); } entryArray = null; } else { mapCache = new HashMap<K, V>(); } } return mapCache; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public void verifyBeforeEmit() { super.verifyBeforeEmit(); if (mapCache != null) { entryArray = new Entry[mapCache.size()]; int index = 0; for (Map.Entry<K, V> entry : mapCache.entrySet()) { entryArray[index++] = new Entry<K, V>(entry); } hashCode = mapCache.hashCode(); mapCache = null; } locked = true; } public boolean isLocked() { return locked; } }