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 }