001 /*--------------------------------------------------------------------------+
002 $Id: HybridMapBase.java 29399 2010-07-27 15:03:17Z juergens $
003 | |
004 | Copyright 2005-2010 Technische Universitaet Muenchen |
005 | |
006 | Licensed under the Apache License, Version 2.0 (the "License"); |
007 | you may not use this file except in compliance with the License. |
008 | You may obtain a copy of the License at |
009 | |
010 | http://www.apache.org/licenses/LICENSE-2.0 |
011 | |
012 | Unless required by applicable law or agreed to in writing, software |
013 | distributed under the License is distributed on an "AS IS" BASIS, |
014 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
015 | See the License for the specific language governing permissions and |
016 | limitations under the License. |
017 +--------------------------------------------------------------------------*/
018 package edu.tum.cs.commons.collections;
019
020 import java.util.Collection;
021 import java.util.Map;
022 import java.util.Set;
023
024 import edu.tum.cs.commons.assertion.CCSMPre;
025
026 /**
027 * A hybrid map is a map which starts with one map implementation, but switches
028 * to another one after a certain size is reached.
029 *
030 * @author hummelb
031 * @author $Author: juergens $
032 * @version $Rev: 29399 $
033 * @levd.rating GREEN Hash: 8464B0259DB7F1270D62FF135895F9FC
034 */
035 public abstract class HybridMapBase<K, V> implements Map<K, V> {
036
037 /** The inner map. */
038 private Map<K, V> map;
039
040 /** Constructor. */
041 protected HybridMapBase(Map<K, V> initialMap) {
042 CCSMPre.isNotNull(initialMap);
043 map = initialMap;
044 }
045
046 /**
047 * Template method for deciding that a switch of map implementation should
048 * be performed before the next insertion. This will be called right before
049 * each put operation. If this returns true, the new map implementation is
050 * obtained via {@link #obtainNewMap()} and all values are copied.
051 *
052 * @param map
053 * the currently used map.
054 * */
055 protected abstract boolean shouldSwitch(Map<K, V> map);
056
057 /**
058 * Template method for obtaining a new map implementation after
059 * {@link #shouldSwitch(Map)} returned true.
060 */
061 protected abstract Map<K, V> obtainNewMap();
062
063 /** {@inheritDoc} */
064 @Override
065 public void clear() {
066 map.clear();
067 }
068
069 /** {@inheritDoc} */
070 @Override
071 public boolean containsKey(Object key) {
072 return map.containsKey(key);
073 }
074
075 /** {@inheritDoc} */
076 @Override
077 public boolean containsValue(Object value) {
078 return map.containsValue(value);
079 }
080
081 /** {@inheritDoc} */
082 @Override
083 public Set<java.util.Map.Entry<K, V>> entrySet() {
084 return map.entrySet();
085 }
086
087 /** {@inheritDoc} */
088 @Override
089 public V get(Object key) {
090 return map.get(key);
091 }
092
093 /** {@inheritDoc} */
094 @Override
095 public boolean isEmpty() {
096 return map.isEmpty();
097 }
098
099 /** {@inheritDoc} */
100 @Override
101 public Set<K> keySet() {
102 return map.keySet();
103 }
104
105 /** {@inheritDoc} */
106 @Override
107 public V put(K key, V value) {
108 if (shouldSwitch(map)) {
109 Map<K, V> oldMap = map;
110 map = obtainNewMap();
111 map.putAll(oldMap);
112 }
113
114 return map.put(key, value);
115 }
116
117 /** {@inheritDoc} */
118 @Override
119 public void putAll(Map<? extends K, ? extends V> m) {
120 map.putAll(m);
121 }
122
123 /** {@inheritDoc} */
124 @Override
125 public V remove(Object key) {
126 return map.remove(key);
127 }
128
129 /** {@inheritDoc} */
130 @Override
131 public int size() {
132 return map.size();
133 }
134
135 /** {@inheritDoc} */
136 @Override
137 public Collection<V> values() {
138 return map.values();
139 }
140 }