1 |
/* AbstractMap.java -- Abstract implementation of most of Map |
/* AbstractMap.java -- Abstract implementation of most of Map |
2 |
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
25 |
executable file might be covered by the GNU General Public License. */ |
executable file might be covered by the GNU General Public License. */ |
26 |
|
|
27 |
|
|
|
// TO DO: |
|
|
// comments |
|
|
// test suite |
|
|
|
|
28 |
package java.util; |
package java.util; |
29 |
|
|
30 |
|
/** |
31 |
|
* An abstract implementation of Map to make it easier to create your own |
32 |
|
* implementations. In order to create an unmodifiable Map, subclass |
33 |
|
* AbstractMap and implement the <code>entrySet</code> (usually via an |
34 |
|
* AbstractSet). To make it modifiable, also implement <code>put</code>, |
35 |
|
* and have <code>entrySet().iterator()</code> support <code>remove</code>. |
36 |
|
* <p> |
37 |
|
* |
38 |
|
* It is recommended that classes which extend this support at least the |
39 |
|
* no-argument constructor, and a constructor which accepts another Map. |
40 |
|
* Further methods in this class may be overridden if you have a more |
41 |
|
* efficient implementation. |
42 |
|
* |
43 |
|
* @author Original author unknown |
44 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
45 |
|
* @see Map |
46 |
|
* @see Collection |
47 |
|
* @see HashMap |
48 |
|
* @see LinkedHashMap |
49 |
|
* @see TreeMap |
50 |
|
* @see WeakHashMap |
51 |
|
* @see IdentityHashMap |
52 |
|
* @since 1.2 |
53 |
|
* @status updated to 1.4 |
54 |
|
*/ |
55 |
public abstract class AbstractMap implements Map |
public abstract class AbstractMap implements Map |
56 |
{ |
{ |
57 |
|
/** An "enum" of iterator types. */ |
58 |
|
// Package visible for use by subclasses. |
59 |
|
static final int KEYS = 0, |
60 |
|
VALUES = 1, |
61 |
|
ENTRIES = 2; |
62 |
|
|
63 |
|
/** |
64 |
|
* The cache for {@link #keySet()}. |
65 |
|
*/ |
66 |
|
// Package visible for use by subclasses. |
67 |
|
Set keys; |
68 |
|
|
69 |
|
/** |
70 |
|
* The cache for {@link #values()}. |
71 |
|
*/ |
72 |
|
// Package visible for use by subclasses. |
73 |
|
Collection values; |
74 |
|
|
75 |
/** |
/** |
76 |
* Remove all entries from this Map. This default implementation calls |
* The main constructor, for use by subclasses. |
77 |
* entrySet().clear(). |
*/ |
78 |
|
protected AbstractMap() |
79 |
|
{ |
80 |
|
} |
81 |
|
|
82 |
|
/** |
83 |
|
* Remove all entries from this Map (optional operation). This default |
84 |
|
* implementation calls entrySet().clear(). NOTE: If the entry set does |
85 |
|
* not permit clearing, then this will fail, too. Subclasses often |
86 |
|
* override this for efficiency. Your implementation of entrySet() should |
87 |
|
* not call <code>AbstractMap.clear</code> unless you want an infinite loop. |
88 |
* |
* |
89 |
* @throws UnsupportedOperationException |
* @throws UnsupportedOperationException if <code>entrySet().clear()</code> |
90 |
* @specnote The JCL book claims that this implementation always throws |
* does not support clearing. |
91 |
* UnsupportedOperationException, while the online docs claim it |
* @see Set#clear() |
|
* calls entrySet().clear(). We take the later to be correct. |
|
92 |
*/ |
*/ |
93 |
public void clear() |
public void clear() |
94 |
{ |
{ |
96 |
} |
} |
97 |
|
|
98 |
/** |
/** |
99 |
* Create a shallow copy of this Map, no keys or values are copied. |
* Create a shallow copy of this Map, no keys or values are copied. The |
100 |
|
* default implementation simply calls <code>super.clone()</code>. |
101 |
|
* |
102 |
|
* @return the shallow clone |
103 |
|
* @throws CloneNotSupportedException if a subclass is not Cloneable |
104 |
|
* @see Cloneable |
105 |
|
* @see Object#clone() |
106 |
*/ |
*/ |
107 |
protected Object clone () throws CloneNotSupportedException |
protected Object clone() throws CloneNotSupportedException |
108 |
{ |
{ |
109 |
return super.clone (); |
AbstractMap copy = (AbstractMap) super.clone(); |
110 |
|
// Clear out the caches; they are stale. |
111 |
|
copy.keys = null; |
112 |
|
copy.values = null; |
113 |
|
return copy; |
114 |
} |
} |
115 |
|
|
116 |
|
/** |
117 |
|
* Returns true if this contains a mapping for the given key. This |
118 |
|
* implementation does a linear search, O(n), over the |
119 |
|
* <code>entrySet()</code>, returning <code>true</code> if a match |
120 |
|
* is found, <code>false</code> if the iteration ends. Many subclasses |
121 |
|
* can implement this more efficiently. |
122 |
|
* |
123 |
|
* @param key the key to search for |
124 |
|
* @return true if the map contains the key |
125 |
|
* @throws NullPointerException if key is <code>null</code> but the map |
126 |
|
* does not permit null keys |
127 |
|
* @see #containsValue(Object) |
128 |
|
*/ |
129 |
public boolean containsKey(Object key) |
public boolean containsKey(Object key) |
130 |
{ |
{ |
131 |
Object k; |
Iterator entries = entrySet().iterator(); |
132 |
Set es = entrySet(); |
int pos = size(); |
133 |
Iterator entries = es.iterator(); |
while (--pos >= 0) |
134 |
int size = size(); |
if (equals(key, ((Map.Entry) entries.next()).getKey())) |
135 |
for (int pos = 0; pos < size; pos++) |
return true; |
|
{ |
|
|
k = ((Map.Entry) entries.next()).getKey(); |
|
|
if (key == null ? k == null : key.equals(k)) |
|
|
return true; |
|
|
} |
|
136 |
return false; |
return false; |
137 |
} |
} |
138 |
|
|
139 |
|
/** |
140 |
|
* Returns true if this contains at least one mapping with the given value. |
141 |
|
* This implementation does a linear search, O(n), over the |
142 |
|
* <code>entrySet()</code>, returning <code>true</code> if a match |
143 |
|
* is found, <code>false</code> if the iteration ends. A match is |
144 |
|
* defined as <code>(value == null ? v == null : value.equals(v))</code> |
145 |
|
* Subclasses are unlikely to implement this more efficiently. |
146 |
|
* |
147 |
|
* @param value the value to search for |
148 |
|
* @return true if the map contains the value |
149 |
|
* @see #containsKey(Object) |
150 |
|
*/ |
151 |
public boolean containsValue(Object value) |
public boolean containsValue(Object value) |
152 |
{ |
{ |
153 |
Object v; |
Iterator entries = entrySet().iterator(); |
154 |
Set es = entrySet(); |
int pos = size(); |
155 |
Iterator entries = es.iterator(); |
while (--pos >= 0) |
156 |
int size = size(); |
if (equals(value, ((Map.Entry) entries.next()).getValue())) |
157 |
for (int pos = 0; pos < size; pos++) |
return true; |
|
{ |
|
|
v = ((Map.Entry) entries.next()).getValue(); |
|
|
if (value == null ? v == null : value.equals(v)) |
|
|
return true; |
|
|
} |
|
158 |
return false; |
return false; |
159 |
} |
} |
160 |
|
|
161 |
|
/** |
162 |
|
* Returns a set view of the mappings in this Map. Each element in the |
163 |
|
* set must be an implementation of Map.Entry. The set is backed by |
164 |
|
* the map, so that changes in one show up in the other. Modifications |
165 |
|
* made while an iterator is in progress cause undefined behavior. If |
166 |
|
* the set supports removal, these methods must be valid: |
167 |
|
* <code>Iterator.remove</code>, <code>Set.remove</code>, |
168 |
|
* <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>. |
169 |
|
* Element addition is not supported via this set. |
170 |
|
* |
171 |
|
* @return the entry set |
172 |
|
* @see Map.Entry |
173 |
|
*/ |
174 |
public abstract Set entrySet(); |
public abstract Set entrySet(); |
175 |
|
|
176 |
|
/** |
177 |
|
* Compares the specified object with this map for equality. Returns |
178 |
|
* <code>true</code> if the other object is a Map with the same mappings, |
179 |
|
* that is,<br> |
180 |
|
* <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code> |
181 |
|
* |
182 |
|
* @param o the object to be compared |
183 |
|
* @return true if the object equals this map |
184 |
|
* @see Set#equals(Object) |
185 |
|
*/ |
186 |
public boolean equals(Object o) |
public boolean equals(Object o) |
187 |
{ |
{ |
188 |
if (o == this) |
return (o == this || |
189 |
return true; |
(o instanceof Map && |
190 |
if (!(o instanceof Map)) |
entrySet().equals(((Map) o).entrySet()))); |
|
return false; |
|
|
|
|
|
Map m = (Map) o; |
|
|
Set s = m.entrySet(); |
|
|
Iterator itr = entrySet().iterator(); |
|
|
int size = size(); |
|
|
|
|
|
if (m.size() != size) |
|
|
return false; |
|
|
|
|
|
for (int pos = 0; pos < size; pos++) |
|
|
{ |
|
|
if (!s.contains(itr.next())) |
|
|
return false; |
|
|
} |
|
|
return true; |
|
191 |
} |
} |
192 |
|
|
193 |
|
/** |
194 |
|
* Returns the value mapped by the given key. Returns <code>null</code> if |
195 |
|
* there is no mapping. However, in Maps that accept null values, you |
196 |
|
* must rely on <code>containsKey</code> to determine if a mapping exists. |
197 |
|
* This iteration takes linear time, searching entrySet().iterator() of |
198 |
|
* the key. Many implementations override this method. |
199 |
|
* |
200 |
|
* @param key the key to look up |
201 |
|
* @return the value associated with the key, or null if key not in map |
202 |
|
* @throws NullPointerException if this map does not accept null keys |
203 |
|
* @see #containsKey(Object) |
204 |
|
*/ |
205 |
public Object get(Object key) |
public Object get(Object key) |
206 |
{ |
{ |
207 |
Set s = entrySet(); |
Iterator entries = entrySet().iterator(); |
208 |
Iterator entries = s.iterator(); |
int pos = size(); |
209 |
int size = size(); |
while (--pos >= 0) |
|
|
|
|
for (int pos = 0; pos < size; pos++) |
|
210 |
{ |
{ |
211 |
Map.Entry entry = (Map.Entry) entries.next(); |
Map.Entry entry = (Map.Entry) entries.next(); |
212 |
Object k = entry.getKey(); |
Object k = entry.getKey(); |
213 |
if (key == null ? k == null : key.equals(k)) |
if (equals(key, k)) |
214 |
return entry.getValue(); |
return entry.getValue(); |
215 |
} |
} |
|
|
|
216 |
return null; |
return null; |
217 |
} |
} |
218 |
|
|
219 |
|
/** |
220 |
|
* Returns the hash code for this map. As defined in Map, this is the sum |
221 |
|
* of all hashcodes for each Map.Entry object in entrySet. |
222 |
|
* |
223 |
|
* @return the hash code |
224 |
|
* @see Map.Entry#hashCode() |
225 |
|
* @see Set#hashCode() |
226 |
|
*/ |
227 |
public int hashCode() |
public int hashCode() |
228 |
{ |
{ |
229 |
int hashcode = 0; |
int hashcode = 0; |
230 |
Iterator itr = entrySet().iterator(); |
Iterator itr = entrySet().iterator(); |
231 |
int size = size(); |
int pos = size(); |
232 |
for (int pos = 0; pos < size; pos++) |
while (--pos >= 0) |
233 |
{ |
hashcode += itr.next().hashCode(); |
|
hashcode += itr.next().hashCode(); |
|
|
} |
|
234 |
return hashcode; |
return hashcode; |
235 |
} |
} |
236 |
|
|
237 |
|
/** |
238 |
|
* Returns true if the map contains no mappings. This is implemented by |
239 |
|
* <code>size() == 0</code>. |
240 |
|
* |
241 |
|
* @return true if the map is empty |
242 |
|
* @see #size() |
243 |
|
*/ |
244 |
public boolean isEmpty() |
public boolean isEmpty() |
245 |
{ |
{ |
246 |
return size() == 0; |
return size() == 0; |
247 |
} |
} |
248 |
|
|
249 |
|
/** |
250 |
|
* Returns a set view of this map's keys. The set is backed by the map, |
251 |
|
* so changes in one show up in the other. Modifications while an iteration |
252 |
|
* is in progress produce undefined behavior. The set supports removal |
253 |
|
* if entrySet() does, but does not support element addition. |
254 |
|
* <p> |
255 |
|
* |
256 |
|
* This implementation creates an AbstractSet, where the iterator wraps |
257 |
|
* the entrySet iterator, size defers to the Map's size, and contains |
258 |
|
* defers to the Map's containsKey. The set is created on first use, and |
259 |
|
* returned on subsequent uses, although since no synchronization occurs, |
260 |
|
* there is a slight possibility of creating two sets. |
261 |
|
* |
262 |
|
* @return a Set view of the keys |
263 |
|
* @see Set#iterator() |
264 |
|
* @see #size() |
265 |
|
* @see #containsKey(Object) |
266 |
|
* @see #values() |
267 |
|
*/ |
268 |
public Set keySet() |
public Set keySet() |
269 |
{ |
{ |
270 |
if (this.keySet == null) |
if (keys == null) |
271 |
|
keys = new AbstractSet() |
272 |
{ |
{ |
273 |
this.keySet = new AbstractSet() |
public int size() |
274 |
{ |
{ |
275 |
public int size() |
return AbstractMap.this.size(); |
276 |
{ |
} |
277 |
return AbstractMap.this.size(); |
|
278 |
} |
public boolean contains(Object key) |
279 |
|
{ |
280 |
public boolean contains(Object key) |
return containsKey(key); |
281 |
{ |
} |
282 |
return AbstractMap.this.containsKey(key); |
|
283 |
} |
public Iterator iterator() |
284 |
|
{ |
285 |
public Iterator iterator() |
return new Iterator() |
286 |
{ |
{ |
287 |
return new Iterator() |
private final Iterator map_iterator = entrySet().iterator(); |
288 |
{ |
|
289 |
Iterator map_iterator = AbstractMap.this.entrySet().iterator(); |
public boolean hasNext() |
290 |
|
{ |
291 |
public boolean hasNext() |
return map_iterator.hasNext(); |
292 |
{ |
} |
293 |
return map_iterator.hasNext(); |
|
294 |
} |
public Object next() |
295 |
|
{ |
296 |
public Object next() |
return ((Map.Entry) map_iterator.next()).getKey(); |
297 |
{ |
} |
298 |
return ((Map.Entry) map_iterator.next()).getKey(); |
|
299 |
} |
public void remove() |
300 |
|
{ |
301 |
public void remove() |
map_iterator.remove(); |
302 |
{ |
} |
303 |
map_iterator.remove(); |
}; |
304 |
} |
} |
305 |
}; |
}; |
306 |
} |
return keys; |
|
}; |
|
|
} |
|
|
|
|
|
return this.keySet; |
|
307 |
} |
} |
308 |
|
|
309 |
|
/** |
310 |
|
* Associates the given key to the given value (optional operation). If the |
311 |
|
* map already contains the key, its value is replaced. This implementation |
312 |
|
* simply throws an UnsupportedOperationException. Be aware that in a map |
313 |
|
* that permits <code>null</code> values, a null return does not always |
314 |
|
* imply that the mapping was created. |
315 |
|
* |
316 |
|
* @param key the key to map |
317 |
|
* @param value the value to be mapped |
318 |
|
* @return the previous value of the key, or null if there was no mapping |
319 |
|
* @throws UnsupportedOperationException if the operation is not supported |
320 |
|
* @throws ClassCastException if the key or value is of the wrong type |
321 |
|
* @throws IllegalArgumentException if something about this key or value |
322 |
|
* prevents it from existing in this map |
323 |
|
* @throws NullPointerException if the map forbids null keys or values |
324 |
|
* @see #containsKey(Object) |
325 |
|
*/ |
326 |
public Object put(Object key, Object value) |
public Object put(Object key, Object value) |
327 |
{ |
{ |
328 |
throw new UnsupportedOperationException(); |
throw new UnsupportedOperationException(); |
329 |
} |
} |
330 |
|
|
331 |
|
/** |
332 |
|
* Copies all entries of the given map to this one (optional operation). If |
333 |
|
* the map already contains a key, its value is replaced. This implementation |
334 |
|
* simply iterates over the map's entrySet(), calling <code>put</code>, |
335 |
|
* so it is not supported if puts are not. |
336 |
|
* |
337 |
|
* @param m the mapping to load into this map |
338 |
|
* @throws UnsupportedOperationException if the operation is not supported |
339 |
|
* @throws ClassCastException if a key or value is of the wrong type |
340 |
|
* @throws IllegalArgumentException if something about a key or value |
341 |
|
* prevents it from existing in this map |
342 |
|
* @throws NullPointerException if the map forbids null keys or values, or |
343 |
|
* if <code>m</code> is null. |
344 |
|
* @see #put(Object, Object) |
345 |
|
*/ |
346 |
public void putAll(Map m) |
public void putAll(Map m) |
347 |
{ |
{ |
|
Map.Entry entry; |
|
348 |
Iterator entries = m.entrySet().iterator(); |
Iterator entries = m.entrySet().iterator(); |
349 |
int size = m.size(); |
int pos = size(); |
350 |
|
while (--pos >= 0) |
|
for (int pos = 0; pos < size; pos++) |
|
351 |
{ |
{ |
352 |
entry = (Map.Entry) entries.next(); |
Map.Entry entry = (Map.Entry) entries.next(); |
353 |
put(entry.getKey(), entry.getValue()); |
put(entry.getKey(), entry.getValue()); |
354 |
} |
} |
355 |
} |
} |
356 |
|
|
357 |
|
/** |
358 |
|
* Removes the mapping for this key if present (optional operation). This |
359 |
|
* implementation iterates over the entrySet searching for a matching |
360 |
|
* key, at which point it calls the iterator's <code>remove</code> method. |
361 |
|
* It returns the result of <code>getValue()</code> on the entry, if found, |
362 |
|
* or null if no entry is found. Note that maps which permit null values |
363 |
|
* may also return null if the key was removed. If the entrySet does not |
364 |
|
* support removal, this will also fail. This is O(n), so many |
365 |
|
* implementations override it for efficiency. |
366 |
|
* |
367 |
|
* @param key the key to remove |
368 |
|
* @return the value the key mapped to, or null if not present |
369 |
|
* @throws UnsupportedOperationException if deletion is unsupported |
370 |
|
* @see Iterator#remove() |
371 |
|
*/ |
372 |
public Object remove(Object key) |
public Object remove(Object key) |
373 |
{ |
{ |
374 |
Iterator entries = entrySet().iterator(); |
Iterator entries = entrySet().iterator(); |
375 |
int size = size(); |
int pos = size(); |
376 |
|
while (--pos >= 0) |
|
for (int pos = 0; pos < size; pos++) |
|
377 |
{ |
{ |
378 |
Map.Entry entry = (Map.Entry) entries.next(); |
Map.Entry entry = (Map.Entry) entries.next(); |
379 |
Object k = entry.getKey(); |
Object k = entry.getKey(); |
380 |
if (key == null ? k == null : key.equals(k)) |
if (equals(key, k)) |
381 |
{ |
{ |
382 |
Object value = entry.getValue(); |
// Must get the value before we remove it from iterator. |
383 |
entries.remove(); |
Object r = entry.getValue(); |
384 |
return value; |
entries.remove(); |
385 |
} |
return r; |
386 |
|
} |
387 |
} |
} |
|
|
|
388 |
return null; |
return null; |
389 |
} |
} |
390 |
|
|
391 |
|
/** |
392 |
|
* Returns the number of key-value mappings in the map. If there are more |
393 |
|
* than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is |
394 |
|
* implemented as <code>entrySet().size()</code>. |
395 |
|
* |
396 |
|
* @return the number of mappings |
397 |
|
* @see Set#size() |
398 |
|
*/ |
399 |
public int size() |
public int size() |
400 |
{ |
{ |
401 |
return entrySet().size(); |
return entrySet().size(); |
402 |
} |
} |
403 |
|
|
404 |
|
/** |
405 |
|
* Returns a String representation of this map. This is a listing of the |
406 |
|
* map entries (which are specified in Map.Entry as being |
407 |
|
* <code>getKey() + "=" + getValue()</code>), separated by a comma and |
408 |
|
* space (", "), and surrounded by braces ('{' and '}'). This implementation |
409 |
|
* uses a StringBuffer and iterates over the entrySet to build the String. |
410 |
|
* Note that this can fail with an exception if underlying keys or |
411 |
|
* values complete abruptly in toString(). |
412 |
|
* |
413 |
|
* @return a String representation |
414 |
|
* @see Map.Entry#toString() |
415 |
|
*/ |
416 |
public String toString() |
public String toString() |
417 |
{ |
{ |
418 |
Iterator entries = entrySet().iterator(); |
Iterator entries = entrySet().iterator(); |
|
int size = size(); |
|
419 |
StringBuffer r = new StringBuffer("{"); |
StringBuffer r = new StringBuffer("{"); |
420 |
for (int pos = 0; pos < size; pos++) |
for (int pos = size(); pos > 0; pos--) |
421 |
{ |
{ |
422 |
// Append the toString value of the entries rather than calling |
// Append the toString value of the entries rather than calling |
423 |
// getKey/getValue. This is more efficient and it matches the JDK |
// getKey/getValue. This is more efficient and it matches the JDK |
424 |
// behaviour. |
// behaviour. |
425 |
r.append(entries.next()); |
r.append(entries.next()); |
426 |
if (pos < size - 1) |
if (pos > 1) |
427 |
r.append(", "); |
r.append(", "); |
428 |
} |
} |
429 |
r.append("}"); |
r.append("}"); |
430 |
return r.toString(); |
return r.toString(); |
431 |
} |
} |
432 |
|
|
433 |
|
/** |
434 |
|
* Returns a collection or bag view of this map's values. The collection |
435 |
|
* is backed by the map, so changes in one show up in the other. |
436 |
|
* Modifications while an iteration is in progress produce undefined |
437 |
|
* behavior. The collection supports removal if entrySet() does, but |
438 |
|
* does not support element addition. |
439 |
|
* <p> |
440 |
|
* |
441 |
|
* This implementation creates an AbstractCollection, where the iterator |
442 |
|
* wraps the entrySet iterator, size defers to the Map's size, and contains |
443 |
|
* defers to the Map's containsValue. The collection is created on first |
444 |
|
* use, and returned on subsequent uses, although since no synchronization |
445 |
|
* occurs, there is a slight possibility of creating two collections. |
446 |
|
* |
447 |
|
* @return a Collection view of the values |
448 |
|
* @see Collection#iterator() |
449 |
|
* @see #size() |
450 |
|
* @see #containsValue(Object) |
451 |
|
* @see #keySet() |
452 |
|
*/ |
453 |
public Collection values() |
public Collection values() |
454 |
{ |
{ |
455 |
if (this.valueCollection == null) |
if (values == null) |
456 |
|
values = new AbstractCollection() |
457 |
{ |
{ |
458 |
this.valueCollection = new AbstractCollection() |
public int size() |
459 |
{ |
{ |
460 |
public int size() |
return AbstractMap.this.size(); |
461 |
{ |
} |
462 |
return AbstractMap.this.size(); |
|
463 |
} |
public Iterator iterator() |
464 |
|
{ |
465 |
public Iterator iterator() |
return new Iterator() |
466 |
{ |
{ |
467 |
return new Iterator() |
Iterator map_iterator = entrySet().iterator(); |
468 |
{ |
|
469 |
Iterator map_iterator = AbstractMap.this.entrySet().iterator(); |
public boolean hasNext() |
470 |
|
{ |
471 |
public boolean hasNext() |
return map_iterator.hasNext(); |
472 |
{ |
} |
473 |
return map_iterator.hasNext(); |
|
474 |
} |
public Object next() |
475 |
|
{ |
476 |
public Object next() |
return ((Map.Entry) map_iterator.next()).getValue(); |
477 |
{ |
} |
478 |
return ((Map.Entry) map_iterator.next()).getValue(); |
|
479 |
} |
public void remove() |
480 |
|
{ |
481 |
public void remove() |
map_iterator.remove(); |
482 |
{ |
} |
483 |
map_iterator.remove(); |
}; |
484 |
} |
} |
485 |
}; |
}; |
486 |
} |
return values; |
487 |
}; |
} |
|
} |
|
488 |
|
|
489 |
return this.valueCollection; |
/** |
490 |
|
* Compare two objects according to Collection semantics. |
491 |
|
* |
492 |
|
* @param o1 the first object |
493 |
|
* @param o2 the second object |
494 |
|
* @return o1 == null ? o2 == null : o1.equals(o2) |
495 |
|
*/ |
496 |
|
// Package visible for use throughout java.util. |
497 |
|
// It may be inlined since it is final. |
498 |
|
static final boolean equals(Object o1, Object o2) |
499 |
|
{ |
500 |
|
return o1 == null ? o2 == null : o1.equals(o2); |
501 |
} |
} |
502 |
|
|
503 |
private Collection valueCollection = null; |
/** |
504 |
private Set keySet = null; |
* Hash an object according to Collection semantics. |
505 |
|
* |
506 |
|
* @param o the object to hash |
507 |
|
* @return o1 == null ? 0 : o1.hashCode() |
508 |
|
*/ |
509 |
|
// Package visible for use throughout java.util. |
510 |
|
// It may be inlined since it is final. |
511 |
|
static final int hashCode(Object o) |
512 |
|
{ |
513 |
|
return o == null ? 0 : o.hashCode(); |
514 |
|
} |
515 |
} |
} |