001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package java.util;
017:
018: /**
019: * Skeletal implementation of the Map interface. <a
020: * href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/AbstractMap.html">[Sun
021: * docs]</a>
022: *
023: * @param <K> the key type.
024: * @param <V> the value type.
025: */
026: public abstract class AbstractMap<K, V> implements Map<K, V> {
027:
028: private static final String MSG_CANNOT_MODIFY = "This map implementation does not support modification";
029:
030: protected AbstractMap() {
031: }
032:
033: public void clear() {
034: entrySet().clear();
035: }
036:
037: public boolean containsKey(Object key) {
038: return implFindEntry(key, false) != null;
039: }
040:
041: public boolean containsValue(Object value) {
042: for (Iterator<Entry<K, V>> iter = entrySet().iterator(); iter
043: .hasNext();) {
044: Entry<K, V> entry = iter.next();
045: V v = entry.getValue();
046: if (value == null ? v == null : value.equals(v)) {
047: return true;
048: }
049: }
050: return false;
051: }
052:
053: public abstract Set<Entry<K, V>> entrySet();
054:
055: @Override
056: public boolean equals(Object obj) {
057: if (obj == this ) {
058: return true;
059: }
060: if (!(obj instanceof Map)) {
061: return false;
062: }
063: Map<?, ?> otherMap = (Map<?, ?>) obj;
064: Set<K> keys = keySet();
065: Set<?> otherKeys = otherMap.keySet();
066: if (!keys.equals(otherKeys)) {
067: return false;
068: }
069: for (Iterator<K> iter = keys.iterator(); iter.hasNext();) {
070: K key = iter.next();
071: V value = get(key);
072: Object otherValue = otherMap.get(key);
073: if (value == null ? otherValue != null : !value
074: .equals(otherValue)) {
075: return false;
076: }
077: }
078: return true;
079: }
080:
081: public V get(Object key) {
082: Map.Entry<K, V> entry = implFindEntry(key, false);
083: return (entry == null ? null : entry.getValue());
084: }
085:
086: @Override
087: public int hashCode() {
088: int hashCode = 0;
089: for (Iterator<Entry<K, V>> iter = entrySet().iterator(); iter
090: .hasNext();) {
091: Entry<K, V> entry = iter.next();
092: hashCode += entry.hashCode();
093: }
094: return hashCode;
095: }
096:
097: public boolean isEmpty() {
098: return size() == 0;
099: }
100:
101: public Set<K> keySet() {
102: final Set<Entry<K, V>> entrySet = entrySet();
103: return new AbstractSet<K>() {
104: @Override
105: public boolean contains(Object key) {
106: return containsKey(key);
107: }
108:
109: @Override
110: public Iterator<K> iterator() {
111: final Iterator<Entry<K, V>> outerIter = entrySet
112: .iterator();
113: return new Iterator<K>() {
114: public boolean hasNext() {
115: return outerIter.hasNext();
116: }
117:
118: public K next() {
119: Map.Entry<K, V> entry = outerIter.next();
120: return entry.getKey();
121: }
122:
123: public void remove() {
124: outerIter.remove();
125: }
126: };
127: }
128:
129: @Override
130: public int size() {
131: return entrySet.size();
132: }
133: };
134: }
135:
136: public V put(K key, V value) {
137: throw new UnsupportedOperationException(MSG_CANNOT_MODIFY);
138: }
139:
140: public void putAll(Map<? extends K, ? extends V> t) {
141: for (Iterator<? extends Entry<? extends K, ? extends V>> iter = t
142: .entrySet().iterator(); iter.hasNext();) {
143: Entry<? extends K, ? extends V> e = iter.next();
144: put(e.getKey(), e.getValue());
145: }
146: }
147:
148: public V remove(Object key) {
149: Map.Entry<K, V> entry = implFindEntry(key, true);
150: return (entry == null ? null : entry.getValue());
151: }
152:
153: public int size() {
154: return entrySet().size();
155: }
156:
157: @Override
158: public String toString() {
159: String s = "{";
160: boolean comma = false;
161: for (Iterator<Entry<K, V>> iter = entrySet().iterator(); iter
162: .hasNext();) {
163: Entry<K, V> entry = iter.next();
164: if (comma) {
165: s += ", ";
166: } else {
167: comma = true;
168: }
169: s += String.valueOf(entry.getKey());
170: s += "=";
171: s += String.valueOf(entry.getValue());
172: }
173: return s + "}";
174: }
175:
176: public Collection<V> values() {
177: final Set<Entry<K, V>> entrySet = entrySet();
178: return new AbstractCollection<V>() {
179: @Override
180: public boolean contains(Object value) {
181: return containsValue(value);
182: }
183:
184: @Override
185: public Iterator<V> iterator() {
186: final Iterator<Entry<K, V>> outerIter = entrySet
187: .iterator();
188: return new Iterator<V>() {
189: public boolean hasNext() {
190: return outerIter.hasNext();
191: }
192:
193: public V next() {
194: V value = outerIter.next().getValue();
195: return value;
196: }
197:
198: public void remove() {
199: outerIter.remove();
200: }
201: };
202: }
203:
204: @Override
205: public int size() {
206: return entrySet.size();
207: }
208: };
209: }
210:
211: private Entry<K, V> implFindEntry(Object key, boolean remove) {
212: for (Iterator<Entry<K, V>> iter = entrySet().iterator(); iter
213: .hasNext();) {
214: Entry<K, V> entry = iter.next();
215: K k = entry.getKey();
216: if (key == null ? k == null : key.equals(k)) {
217: if (remove) {
218: iter.remove();
219: }
220: return entry;
221: }
222: }
223: return null;
224: }
225: }
|