/* * Copyright 2005, 2006 Gregory Block, Ralf Joachim * * 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.castor.cache.hashbelt.container; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * The FastIteratingContainer implementation of the Container interface assuems two * things: * <ul> * <li>Puts and removes are rare in proportion to gets and iteration are common. * Put and remove are much more expensive here than in MapContainer.</li> * <li>Keys will not be reused (using a key twice with different values implicitly * does an expensive remove).</li> * </ul> * In order for allow for removes and adds to be called while an iterator is in use, * iterator-responses use cloned key/value lists. * * @author <a href="mailto:gblock AT ctoforaday DOT com">Gregory Block</a> * @author <a href="mailto:ralf DOT joachim AT syscon DOT eu">Ralf Joachim</a> * @version $Revision$ $Date: 2006-04-25 16:09:10 -0600 (Tue, 25 Apr 2006) $ * @since 1.0 */ public final class FastIteratingContainer implements Container { //-------------------------------------------------------------------------- /** The hashmap to store key/value pairs. */ private Map<Object, Object> _container = new ConcurrentHashMap<Object, Object>(); /** List of keys in the container. */ private List<Object> _keys = new ArrayList<Object>(); /** List of values in the container. */ private List<Object> _values = new ArrayList<Object>(); /** Timestamp of this container. */ private long _timestamp = 0; //-------------------------------------------------------------------------- // additional operations of container interface /** * {@inheritDoc} */ public void updateTimestamp() { _timestamp = System.currentTimeMillis(); } /** * {@inheritDoc} */ public long getTimestamp() { return _timestamp; } /** * {@inheritDoc} */ public synchronized Iterator<Object> keyIterator() { return new ArrayList<Object>(_keys).iterator(); } /** * {@inheritDoc} */ public synchronized Iterator<Object> valueIterator() { return new ArrayList<Object>(_values).iterator(); } //-------------------------------------------------------------------------- // query operations of map interface /** * {@inheritDoc} */ public int size() { return _container.size(); } /** * {@inheritDoc} */ public boolean isEmpty() { return _container.isEmpty(); } /** * {@inheritDoc} */ public boolean containsKey(final Object key) { return _container.containsKey(key); } /** * {@inheritDoc} */ public boolean containsValue(final Object value) { return _container.containsValue(value); } /** * {@inheritDoc} */ public Object get(final Object key) { return _container.get(key); } //-------------------------------------------------------------------------- // modification operations of map interface /** * {@inheritDoc} */ public Object put(final Object key, final Object value) { if (value == null) { throw new IllegalArgumentException(); } Object oldValue = _container.put(key, value); if (oldValue == null) { synchronized (this) { _keys.add(key); _values.add(value); } } else if (oldValue != value) { synchronized (this) { _values.remove(oldValue); _values.add(value); } } return oldValue; } /** * {@inheritDoc} */ public Object remove(final Object key) { Object oldValue = _container.remove(key); if (oldValue != null) { synchronized (this) { _keys.remove(key); _values.remove(oldValue); } } return oldValue; } //-------------------------------------------------------------------------- // bulk operations of map interface /** * {@inheritDoc} */ public synchronized void putAll(final Map<? extends Object, ? extends Object> map) { Iterator<? extends Entry<? extends Object, ? extends Object>> iter; iter = map.entrySet().iterator(); while (iter.hasNext()) { Entry<? extends Object, ? extends Object> entry = iter.next(); put(entry.getKey(), entry.getValue()); } } /** * {@inheritDoc} */ public void clear() { _container.clear(); synchronized (this) { _keys.clear(); _values.clear(); } } //-------------------------------------------------------------------------- // view operations of map interface /** * {@inheritDoc} */ public Set<Object> keySet() { return _container.keySet(); } /** * {@inheritDoc} */ public Collection<Object> values() { return _container.values(); } /** * {@inheritDoc} */ public Set<Entry<Object, Object>> entrySet() { return _container.entrySet(); } //-------------------------------------------------------------------------- }