Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
FastHashMap |
|
| 2.6530612244897958;2.653 | ||||
FastHashMap$1 |
|
| 2.6530612244897958;2.653 | ||||
FastHashMap$CollectionView |
|
| 2.6530612244897958;2.653 | ||||
FastHashMap$CollectionView$CollectionViewIterator |
|
| 2.6530612244897958;2.653 | ||||
FastHashMap$EntrySet |
|
| 2.6530612244897958;2.653 | ||||
FastHashMap$KeySet |
|
| 2.6530612244897958;2.653 | ||||
FastHashMap$Values |
|
| 2.6530612244897958;2.653 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | * contributor license agreements. See the NOTICE file distributed with | |
4 | * this work for additional information regarding copyright ownership. | |
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | * (the "License"); you may not use this file except in compliance with | |
7 | * the License. You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | package org.apache.commons.collections; | |
18 | ||
19 | import java.util.Collection; | |
20 | import java.util.ConcurrentModificationException; | |
21 | import java.util.HashMap; | |
22 | import java.util.Iterator; | |
23 | import java.util.Map; | |
24 | import java.util.Set; | |
25 | ||
26 | /** | |
27 | * <p>A customized implementation of <code>java.util.HashMap</code> designed | |
28 | * to operate in a multithreaded environment where the large majority of | |
29 | * method calls are read-only, instead of structural changes. When operating | |
30 | * in "fast" mode, read calls are non-synchronized and write calls perform the | |
31 | * following steps:</p> | |
32 | * <ul> | |
33 | * <li>Clone the existing collection | |
34 | * <li>Perform the modification on the clone | |
35 | * <li>Replace the existing collection with the (modified) clone | |
36 | * </ul> | |
37 | * <p>When first created, objects of this class default to "slow" mode, where | |
38 | * all accesses of any type are synchronized but no cloning takes place. This | |
39 | * is appropriate for initially populating the collection, followed by a switch | |
40 | * to "fast" mode (by calling <code>setFast(true)</code>) after initialization | |
41 | * is complete.</p> | |
42 | * | |
43 | * <p><strong>NOTE</strong>: If you are creating and accessing a | |
44 | * <code>HashMap</code> only within a single thread, you should use | |
45 | * <code>java.util.HashMap</code> directly (with no synchronization), for | |
46 | * maximum performance.</p> | |
47 | * | |
48 | * <p><strong>NOTE</strong>: <i>This class is not cross-platform. | |
49 | * Using it may cause unexpected failures on some architectures.</i> | |
50 | * It suffers from the same problems as the double-checked locking idiom. | |
51 | * In particular, the instruction that clones the internal collection and the | |
52 | * instruction that sets the internal reference to the clone can be executed | |
53 | * or perceived out-of-order. This means that any read operation might fail | |
54 | * unexpectedly, as it may be reading the state of the internal collection | |
55 | * before the internal collection is fully formed. | |
56 | * For more information on the double-checked locking idiom, see the | |
57 | * <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html"> | |
58 | * Double-Checked Locking Idiom Is Broken Declaration</a>.</p> | |
59 | * | |
60 | * @since Commons Collections 1.0 | |
61 | * @version $Revision: 555845 $ $Date: 2007-07-12 22:52:05 -0400 (Thu, 12 Jul 2007) $ | |
62 | * | |
63 | * @author Craig R. McClanahan | |
64 | * @author Stephen Colebourne | |
65 | */ | |
66 | public class FastHashMap extends HashMap { | |
67 | ||
68 | /** | |
69 | * The underlying map we are managing. | |
70 | */ | |
71 | 67 | protected HashMap map = null; |
72 | ||
73 | /** | |
74 | * Are we currently operating in "fast" mode? | |
75 | */ | |
76 | 67 | protected boolean fast = false; |
77 | ||
78 | // Constructors | |
79 | // ---------------------------------------------------------------------- | |
80 | ||
81 | /** | |
82 | * Construct an empty map. | |
83 | */ | |
84 | public FastHashMap() { | |
85 | 67 | super(); |
86 | 67 | this.map = new HashMap(); |
87 | 67 | } |
88 | ||
89 | /** | |
90 | * Construct an empty map with the specified capacity. | |
91 | * | |
92 | * @param capacity the initial capacity of the empty map | |
93 | */ | |
94 | public FastHashMap(int capacity) { | |
95 | 0 | super(); |
96 | 0 | this.map = new HashMap(capacity); |
97 | 0 | } |
98 | ||
99 | /** | |
100 | * Construct an empty map with the specified capacity and load factor. | |
101 | * | |
102 | * @param capacity the initial capacity of the empty map | |
103 | * @param factor the load factor of the new map | |
104 | */ | |
105 | public FastHashMap(int capacity, float factor) { | |
106 | 0 | super(); |
107 | 0 | this.map = new HashMap(capacity, factor); |
108 | 0 | } |
109 | ||
110 | /** | |
111 | * Construct a new map with the same mappings as the specified map. | |
112 | * | |
113 | * @param map the map whose mappings are to be copied | |
114 | */ | |
115 | public FastHashMap(Map map) { | |
116 | 0 | super(); |
117 | 0 | this.map = new HashMap(map); |
118 | 0 | } |
119 | ||
120 | ||
121 | // Property access | |
122 | // ---------------------------------------------------------------------- | |
123 | ||
124 | /** | |
125 | * Returns true if this map is operating in fast mode. | |
126 | * | |
127 | * @return true if this map is operating in fast mode | |
128 | */ | |
129 | public boolean getFast() { | |
130 | 0 | return (this.fast); |
131 | } | |
132 | ||
133 | /** | |
134 | * Sets whether this map is operating in fast mode. | |
135 | * | |
136 | * @param fast true if this map should operate in fast mode | |
137 | */ | |
138 | public void setFast(boolean fast) { | |
139 | 21 | this.fast = fast; |
140 | 21 | } |
141 | ||
142 | ||
143 | // Map access | |
144 | // ---------------------------------------------------------------------- | |
145 | // These methods can forward straight to the wrapped Map in 'fast' mode. | |
146 | // (because they are query methods) | |
147 | ||
148 | /** | |
149 | * Return the value to which this map maps the specified key. Returns | |
150 | * <code>null</code> if the map contains no mapping for this key, or if | |
151 | * there is a mapping with a value of <code>null</code>. Use the | |
152 | * <code>containsKey()</code> method to disambiguate these cases. | |
153 | * | |
154 | * @param key the key whose value is to be returned | |
155 | * @return the value mapped to that key, or null | |
156 | */ | |
157 | public Object get(Object key) { | |
158 | 188 | if (fast) { |
159 | 188 | return (map.get(key)); |
160 | } else { | |
161 | 0 | synchronized (map) { |
162 | 0 | return (map.get(key)); |
163 | 0 | } |
164 | } | |
165 | } | |
166 | ||
167 | /** | |
168 | * Return the number of key-value mappings in this map. | |
169 | * | |
170 | * @return the current size of the map | |
171 | */ | |
172 | public int size() { | |
173 | 3 | if (fast) { |
174 | 3 | return (map.size()); |
175 | } else { | |
176 | 0 | synchronized (map) { |
177 | 0 | return (map.size()); |
178 | 0 | } |
179 | } | |
180 | } | |
181 | ||
182 | /** | |
183 | * Return <code>true</code> if this map contains no mappings. | |
184 | * | |
185 | * @return is the map currently empty | |
186 | */ | |
187 | public boolean isEmpty() { | |
188 | 0 | if (fast) { |
189 | 0 | return (map.isEmpty()); |
190 | } else { | |
191 | 0 | synchronized (map) { |
192 | 0 | return (map.isEmpty()); |
193 | 0 | } |
194 | } | |
195 | } | |
196 | ||
197 | /** | |
198 | * Return <code>true</code> if this map contains a mapping for the | |
199 | * specified key. | |
200 | * | |
201 | * @param key the key to be searched for | |
202 | * @return true if the map contains the key | |
203 | */ | |
204 | public boolean containsKey(Object key) { | |
205 | 0 | if (fast) { |
206 | 0 | return (map.containsKey(key)); |
207 | } else { | |
208 | 0 | synchronized (map) { |
209 | 0 | return (map.containsKey(key)); |
210 | 0 | } |
211 | } | |
212 | } | |
213 | ||
214 | /** | |
215 | * Return <code>true</code> if this map contains one or more keys mapping | |
216 | * to the specified value. | |
217 | * | |
218 | * @param value the value to be searched for | |
219 | * @return true if the map contains the value | |
220 | */ | |
221 | public boolean containsValue(Object value) { | |
222 | 0 | if (fast) { |
223 | 0 | return (map.containsValue(value)); |
224 | } else { | |
225 | 0 | synchronized (map) { |
226 | 0 | return (map.containsValue(value)); |
227 | 0 | } |
228 | } | |
229 | } | |
230 | ||
231 | // Map modification | |
232 | // ---------------------------------------------------------------------- | |
233 | // These methods perform special behaviour in 'fast' mode. | |
234 | // The map is cloned, updated and then assigned back. | |
235 | // See the comments at the top as to why this won't always work. | |
236 | ||
237 | /** | |
238 | * Associate the specified value with the specified key in this map. | |
239 | * If the map previously contained a mapping for this key, the old | |
240 | * value is replaced and returned. | |
241 | * | |
242 | * @param key the key with which the value is to be associated | |
243 | * @param value the value to be associated with this key | |
244 | * @return the value previously mapped to the key, or null | |
245 | */ | |
246 | public Object put(Object key, Object value) { | |
247 | 20 | if (fast) { |
248 | 20 | synchronized (this) { |
249 | 20 | HashMap temp = (HashMap) map.clone(); |
250 | 20 | Object result = temp.put(key, value); |
251 | 20 | map = temp; |
252 | 20 | return (result); |
253 | 0 | } |
254 | } else { | |
255 | 0 | synchronized (map) { |
256 | 0 | return (map.put(key, value)); |
257 | 0 | } |
258 | } | |
259 | } | |
260 | ||
261 | /** | |
262 | * Copy all of the mappings from the specified map to this one, replacing | |
263 | * any mappings with the same keys. | |
264 | * | |
265 | * @param in the map whose mappings are to be copied | |
266 | */ | |
267 | public void putAll(Map in) { | |
268 | 0 | if (fast) { |
269 | 0 | synchronized (this) { |
270 | 0 | HashMap temp = (HashMap) map.clone(); |
271 | 0 | temp.putAll(in); |
272 | 0 | map = temp; |
273 | 0 | } |
274 | } else { | |
275 | 0 | synchronized (map) { |
276 | 0 | map.putAll(in); |
277 | 0 | } |
278 | } | |
279 | 0 | } |
280 | ||
281 | /** | |
282 | * Remove any mapping for this key, and return any previously | |
283 | * mapped value. | |
284 | * | |
285 | * @param key the key whose mapping is to be removed | |
286 | * @return the value removed, or null | |
287 | */ | |
288 | public Object remove(Object key) { | |
289 | 0 | if (fast) { |
290 | 0 | synchronized (this) { |
291 | 0 | HashMap temp = (HashMap) map.clone(); |
292 | 0 | Object result = temp.remove(key); |
293 | 0 | map = temp; |
294 | 0 | return (result); |
295 | 0 | } |
296 | } else { | |
297 | 0 | synchronized (map) { |
298 | 0 | return (map.remove(key)); |
299 | 0 | } |
300 | } | |
301 | } | |
302 | ||
303 | /** | |
304 | * Remove all mappings from this map. | |
305 | */ | |
306 | public void clear() { | |
307 | 0 | if (fast) { |
308 | 0 | synchronized (this) { |
309 | 0 | map = new HashMap(); |
310 | 0 | } |
311 | } else { | |
312 | 0 | synchronized (map) { |
313 | 0 | map.clear(); |
314 | 0 | } |
315 | } | |
316 | 0 | } |
317 | ||
318 | // Basic object methods | |
319 | // ---------------------------------------------------------------------- | |
320 | ||
321 | /** | |
322 | * Compare the specified object with this list for equality. This | |
323 | * implementation uses exactly the code that is used to define the | |
324 | * list equals function in the documentation for the | |
325 | * <code>Map.equals</code> method. | |
326 | * | |
327 | * @param o the object to be compared to this list | |
328 | * @return true if the two maps are equal | |
329 | */ | |
330 | public boolean equals(Object o) { | |
331 | // Simple tests that require no synchronization | |
332 | 0 | if (o == this) { |
333 | 0 | return (true); |
334 | 0 | } else if (!(o instanceof Map)) { |
335 | 0 | return (false); |
336 | } | |
337 | 0 | Map mo = (Map) o; |
338 | ||
339 | // Compare the two maps for equality | |
340 | 0 | if (fast) { |
341 | 0 | if (mo.size() != map.size()) { |
342 | 0 | return (false); |
343 | } | |
344 | 0 | Iterator i = map.entrySet().iterator(); |
345 | 0 | while (i.hasNext()) { |
346 | 0 | Map.Entry e = (Map.Entry) i.next(); |
347 | 0 | Object key = e.getKey(); |
348 | 0 | Object value = e.getValue(); |
349 | 0 | if (value == null) { |
350 | 0 | if (!(mo.get(key) == null && mo.containsKey(key))) { |
351 | 0 | return (false); |
352 | } | |
353 | } else { | |
354 | 0 | if (!value.equals(mo.get(key))) { |
355 | 0 | return (false); |
356 | } | |
357 | } | |
358 | 0 | } |
359 | 0 | return (true); |
360 | ||
361 | } else { | |
362 | 0 | synchronized (map) { |
363 | 0 | if (mo.size() != map.size()) { |
364 | 0 | return (false); |
365 | } | |
366 | 0 | Iterator i = map.entrySet().iterator(); |
367 | 0 | while (i.hasNext()) { |
368 | 0 | Map.Entry e = (Map.Entry) i.next(); |
369 | 0 | Object key = e.getKey(); |
370 | 0 | Object value = e.getValue(); |
371 | 0 | if (value == null) { |
372 | 0 | if (!(mo.get(key) == null && mo.containsKey(key))) { |
373 | 0 | return (false); |
374 | } | |
375 | } else { | |
376 | 0 | if (!value.equals(mo.get(key))) { |
377 | 0 | return (false); |
378 | } | |
379 | } | |
380 | 0 | } |
381 | 0 | return (true); |
382 | 0 | } |
383 | } | |
384 | } | |
385 | ||
386 | /** | |
387 | * Return the hash code value for this map. This implementation uses | |
388 | * exactly the code that is used to define the list hash function in the | |
389 | * documentation for the <code>Map.hashCode</code> method. | |
390 | * | |
391 | * @return suitable integer hash code | |
392 | */ | |
393 | public int hashCode() { | |
394 | 0 | if (fast) { |
395 | 0 | int h = 0; |
396 | 0 | Iterator i = map.entrySet().iterator(); |
397 | 0 | while (i.hasNext()) { |
398 | 0 | h += i.next().hashCode(); |
399 | } | |
400 | 0 | return (h); |
401 | } else { | |
402 | 0 | synchronized (map) { |
403 | 0 | int h = 0; |
404 | 0 | Iterator i = map.entrySet().iterator(); |
405 | 0 | while (i.hasNext()) { |
406 | 0 | h += i.next().hashCode(); |
407 | } | |
408 | 0 | return (h); |
409 | 0 | } |
410 | } | |
411 | } | |
412 | ||
413 | /** | |
414 | * Return a shallow copy of this <code>FastHashMap</code> instance. | |
415 | * The keys and values themselves are not copied. | |
416 | * | |
417 | * @return a clone of this map | |
418 | */ | |
419 | public Object clone() { | |
420 | 0 | FastHashMap results = null; |
421 | 0 | if (fast) { |
422 | 0 | results = new FastHashMap(map); |
423 | } else { | |
424 | 0 | synchronized (map) { |
425 | 0 | results = new FastHashMap(map); |
426 | 0 | } |
427 | } | |
428 | 0 | results.setFast(getFast()); |
429 | 0 | return (results); |
430 | } | |
431 | ||
432 | // Map views | |
433 | // ---------------------------------------------------------------------- | |
434 | ||
435 | /** | |
436 | * Return a collection view of the mappings contained in this map. Each | |
437 | * element in the returned collection is a <code>Map.Entry</code>. | |
438 | * @return the set of map Map entries | |
439 | */ | |
440 | public Set entrySet() { | |
441 | 0 | return new EntrySet(); |
442 | } | |
443 | ||
444 | /** | |
445 | * Return a set view of the keys contained in this map. | |
446 | * @return the set of the Map's keys | |
447 | */ | |
448 | public Set keySet() { | |
449 | 3 | return new KeySet(); |
450 | } | |
451 | ||
452 | /** | |
453 | * Return a collection view of the values contained in this map. | |
454 | * @return the set of the Map's values | |
455 | */ | |
456 | public Collection values() { | |
457 | 0 | return new Values(); |
458 | } | |
459 | ||
460 | // Map view inner classes | |
461 | // ---------------------------------------------------------------------- | |
462 | ||
463 | /** | |
464 | * Abstract collection implementation shared by keySet(), values() and entrySet(). | |
465 | */ | |
466 | private abstract class CollectionView implements Collection { | |
467 | ||
468 | 3 | public CollectionView() { |
469 | 3 | } |
470 | ||
471 | protected abstract Collection get(Map map); | |
472 | protected abstract Object iteratorNext(Map.Entry entry); | |
473 | ||
474 | ||
475 | public void clear() { | |
476 | 0 | if (fast) { |
477 | 0 | synchronized (FastHashMap.this) { |
478 | 0 | map = new HashMap(); |
479 | 0 | } |
480 | } else { | |
481 | 0 | synchronized (map) { |
482 | 0 | get(map).clear(); |
483 | 0 | } |
484 | } | |
485 | 0 | } |
486 | ||
487 | public boolean remove(Object o) { | |
488 | 0 | if (fast) { |
489 | 0 | synchronized (FastHashMap.this) { |
490 | 0 | HashMap temp = (HashMap) map.clone(); |
491 | 0 | boolean r = get(temp).remove(o); |
492 | 0 | map = temp; |
493 | 0 | return r; |
494 | 0 | } |
495 | } else { | |
496 | 0 | synchronized (map) { |
497 | 0 | return get(map).remove(o); |
498 | 0 | } |
499 | } | |
500 | } | |
501 | ||
502 | public boolean removeAll(Collection o) { | |
503 | 0 | if (fast) { |
504 | 0 | synchronized (FastHashMap.this) { |
505 | 0 | HashMap temp = (HashMap) map.clone(); |
506 | 0 | boolean r = get(temp).removeAll(o); |
507 | 0 | map = temp; |
508 | 0 | return r; |
509 | 0 | } |
510 | } else { | |
511 | 0 | synchronized (map) { |
512 | 0 | return get(map).removeAll(o); |
513 | 0 | } |
514 | } | |
515 | } | |
516 | ||
517 | public boolean retainAll(Collection o) { | |
518 | 0 | if (fast) { |
519 | 0 | synchronized (FastHashMap.this) { |
520 | 0 | HashMap temp = (HashMap) map.clone(); |
521 | 0 | boolean r = get(temp).retainAll(o); |
522 | 0 | map = temp; |
523 | 0 | return r; |
524 | 0 | } |
525 | } else { | |
526 | 0 | synchronized (map) { |
527 | 0 | return get(map).retainAll(o); |
528 | 0 | } |
529 | } | |
530 | } | |
531 | ||
532 | public int size() { | |
533 | 0 | if (fast) { |
534 | 0 | return get(map).size(); |
535 | } else { | |
536 | 0 | synchronized (map) { |
537 | 0 | return get(map).size(); |
538 | 0 | } |
539 | } | |
540 | } | |
541 | ||
542 | ||
543 | public boolean isEmpty() { | |
544 | 0 | if (fast) { |
545 | 0 | return get(map).isEmpty(); |
546 | } else { | |
547 | 0 | synchronized (map) { |
548 | 0 | return get(map).isEmpty(); |
549 | 0 | } |
550 | } | |
551 | } | |
552 | ||
553 | public boolean contains(Object o) { | |
554 | 0 | if (fast) { |
555 | 0 | return get(map).contains(o); |
556 | } else { | |
557 | 0 | synchronized (map) { |
558 | 0 | return get(map).contains(o); |
559 | 0 | } |
560 | } | |
561 | } | |
562 | ||
563 | public boolean containsAll(Collection o) { | |
564 | 0 | if (fast) { |
565 | 0 | return get(map).containsAll(o); |
566 | } else { | |
567 | 0 | synchronized (map) { |
568 | 0 | return get(map).containsAll(o); |
569 | 0 | } |
570 | } | |
571 | } | |
572 | ||
573 | public Object[] toArray(Object[] o) { | |
574 | 0 | if (fast) { |
575 | 0 | return get(map).toArray(o); |
576 | } else { | |
577 | 0 | synchronized (map) { |
578 | 0 | return get(map).toArray(o); |
579 | 0 | } |
580 | } | |
581 | } | |
582 | ||
583 | public Object[] toArray() { | |
584 | 0 | if (fast) { |
585 | 0 | return get(map).toArray(); |
586 | } else { | |
587 | 0 | synchronized (map) { |
588 | 0 | return get(map).toArray(); |
589 | 0 | } |
590 | } | |
591 | } | |
592 | ||
593 | ||
594 | public boolean equals(Object o) { | |
595 | 0 | if (o == this) { |
596 | 0 | return true; |
597 | } | |
598 | 0 | if (fast) { |
599 | 0 | return get(map).equals(o); |
600 | } else { | |
601 | 0 | synchronized (map) { |
602 | 0 | return get(map).equals(o); |
603 | 0 | } |
604 | } | |
605 | } | |
606 | ||
607 | public int hashCode() { | |
608 | 0 | if (fast) { |
609 | 0 | return get(map).hashCode(); |
610 | } else { | |
611 | 0 | synchronized (map) { |
612 | 0 | return get(map).hashCode(); |
613 | 0 | } |
614 | } | |
615 | } | |
616 | ||
617 | public boolean add(Object o) { | |
618 | 0 | throw new UnsupportedOperationException(); |
619 | } | |
620 | ||
621 | public boolean addAll(Collection c) { | |
622 | 0 | throw new UnsupportedOperationException(); |
623 | } | |
624 | ||
625 | public Iterator iterator() { | |
626 | 3 | return new CollectionViewIterator(); |
627 | } | |
628 | ||
629 | private class CollectionViewIterator implements Iterator { | |
630 | ||
631 | private Map expected; | |
632 | 3 | private Map.Entry lastReturned = null; |
633 | private Iterator iterator; | |
634 | ||
635 | 3 | public CollectionViewIterator() { |
636 | 3 | this.expected = map; |
637 | 3 | this.iterator = expected.entrySet().iterator(); |
638 | 3 | } |
639 | ||
640 | public boolean hasNext() { | |
641 | 8 | if (expected != map) { |
642 | 0 | throw new ConcurrentModificationException(); |
643 | } | |
644 | 8 | return iterator.hasNext(); |
645 | } | |
646 | ||
647 | public Object next() { | |
648 | 5 | if (expected != map) { |
649 | 0 | throw new ConcurrentModificationException(); |
650 | } | |
651 | 5 | lastReturned = (Map.Entry)iterator.next(); |
652 | 5 | return iteratorNext(lastReturned); |
653 | } | |
654 | ||
655 | public void remove() { | |
656 | 0 | if (lastReturned == null) { |
657 | 0 | throw new IllegalStateException(); |
658 | } | |
659 | 0 | if (fast) { |
660 | 0 | synchronized (FastHashMap.this) { |
661 | 0 | if (expected != map) { |
662 | 0 | throw new ConcurrentModificationException(); |
663 | } | |
664 | 0 | FastHashMap.this.remove(lastReturned.getKey()); |
665 | 0 | lastReturned = null; |
666 | 0 | expected = map; |
667 | 0 | } |
668 | } else { | |
669 | 0 | iterator.remove(); |
670 | 0 | lastReturned = null; |
671 | } | |
672 | 0 | } |
673 | } | |
674 | } | |
675 | ||
676 | /** | |
677 | * Set implementation over the keys of the FastHashMap | |
678 | */ | |
679 | 6 | private class KeySet extends CollectionView implements Set { |
680 | ||
681 | protected Collection get(Map map) { | |
682 | 0 | return map.keySet(); |
683 | } | |
684 | ||
685 | protected Object iteratorNext(Map.Entry entry) { | |
686 | 5 | return entry.getKey(); |
687 | } | |
688 | ||
689 | } | |
690 | ||
691 | /** | |
692 | * Collection implementation over the values of the FastHashMap | |
693 | */ | |
694 | 0 | private class Values extends CollectionView { |
695 | ||
696 | protected Collection get(Map map) { | |
697 | 0 | return map.values(); |
698 | } | |
699 | ||
700 | protected Object iteratorNext(Map.Entry entry) { | |
701 | 0 | return entry.getValue(); |
702 | } | |
703 | } | |
704 | ||
705 | /** | |
706 | * Set implementation over the entries of the FastHashMap | |
707 | */ | |
708 | 0 | private class EntrySet extends CollectionView implements Set { |
709 | ||
710 | protected Collection get(Map map) { | |
711 | 0 | return map.entrySet(); |
712 | } | |
713 | ||
714 | protected Object iteratorNext(Map.Entry entry) { | |
715 | 0 | return entry; |
716 | } | |
717 | ||
718 | } | |
719 | ||
720 | } |