1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.map;
18
19 import java.util.ConcurrentModificationException;
20 import java.util.Iterator;
21 import java.util.Map;
22 import java.util.NoSuchElementException;
23 import java.util.Objects;
24
25 import org.apache.commons.collections4.OrderedIterator;
26 import org.apache.commons.collections4.OrderedMap;
27 import org.apache.commons.collections4.OrderedMapIterator;
28 import org.apache.commons.collections4.ResettableIterator;
29 import org.apache.commons.collections4.iterators.EmptyOrderedIterator;
30 import org.apache.commons.collections4.iterators.EmptyOrderedMapIterator;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public abstract class AbstractLinkedMap<K, V> extends AbstractHashedMap<K, V> implements OrderedMap<K, V> {
71
72
73
74
75
76
77
78 protected static class EntrySetIterator<K, V> extends LinkIterator<K, V> implements
79 OrderedIterator<Map.Entry<K, V>>, ResettableIterator<Map.Entry<K, V>> {
80
81
82
83
84
85
86 protected EntrySetIterator(final AbstractLinkedMap<K, V> parent) {
87 super(parent);
88 }
89
90 @Override
91 public Map.Entry<K, V> next() {
92 return super.nextEntry();
93 }
94
95 @Override
96 public Map.Entry<K, V> previous() {
97 return super.previousEntry();
98 }
99 }
100
101
102
103
104
105
106 protected static class KeySetIterator<K> extends LinkIterator<K, Object> implements
107 OrderedIterator<K>, ResettableIterator<K> {
108
109
110
111
112
113
114 @SuppressWarnings("unchecked")
115 protected KeySetIterator(final AbstractLinkedMap<K, ?> parent) {
116 super((AbstractLinkedMap<K, Object>) parent);
117 }
118
119 @Override
120 public K next() {
121 return super.nextEntry().getKey();
122 }
123
124 @Override
125 public K previous() {
126 return super.previousEntry().getKey();
127 }
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141
142 protected static class LinkEntry<K, V> extends HashEntry<K, V> {
143
144 protected LinkEntry<K, V> before;
145
146 protected LinkEntry<K, V> after;
147
148
149
150
151
152
153
154
155
156 protected LinkEntry(final HashEntry<K, V> next, final int hashCode, final Object key, final V value) {
157 super(next, hashCode, key, value);
158 }
159 }
160
161
162
163
164
165
166
167 protected abstract static class LinkIterator<K, V> {
168
169
170 protected final AbstractLinkedMap<K, V> parent;
171
172
173 protected LinkEntry<K, V> last;
174
175
176 protected LinkEntry<K, V> next;
177
178
179 protected int expectedModCount;
180
181
182
183
184
185
186 protected LinkIterator(final AbstractLinkedMap<K, V> parent) {
187 this.parent = Objects.requireNonNull(parent);
188 this.next = parent.header.after;
189 this.expectedModCount = parent.modCount;
190 }
191
192
193
194
195
196
197 protected LinkEntry<K, V> currentEntry() {
198 return last;
199 }
200
201
202
203
204
205
206 public boolean hasNext() {
207 return next != parent.header;
208 }
209
210
211
212
213
214
215 public boolean hasPrevious() {
216 return next.before != parent.header;
217 }
218
219
220
221
222
223
224 protected LinkEntry<K, V> nextEntry() {
225 if (parent.modCount != expectedModCount) {
226 throw new ConcurrentModificationException();
227 }
228 if (next == parent.header) {
229 throw new NoSuchElementException(NO_NEXT_ENTRY);
230 }
231 last = next;
232 next = next.after;
233 return last;
234 }
235
236
237
238
239
240
241 protected LinkEntry<K, V> previousEntry() {
242 if (parent.modCount != expectedModCount) {
243 throw new ConcurrentModificationException();
244 }
245 final LinkEntry<K, V> previous = next.before;
246 if (previous == parent.header) {
247 throw new NoSuchElementException(NO_PREVIOUS_ENTRY);
248 }
249 next = previous;
250 last = previous;
251 return last;
252 }
253
254
255
256
257 public void remove() {
258 if (last == null) {
259 throw new IllegalStateException(REMOVE_INVALID);
260 }
261 if (parent.modCount != expectedModCount) {
262 throw new ConcurrentModificationException();
263 }
264 parent.remove(last.getKey());
265 last = null;
266 expectedModCount = parent.modCount;
267 }
268
269
270
271
272 public void reset() {
273 last = null;
274 next = parent.header.after;
275 }
276
277 @Override
278 public String toString() {
279 if (last != null) {
280 return "Iterator[" + last.getKey() + "=" + last.getValue() + "]";
281 }
282 return "Iterator[]";
283 }
284 }
285
286
287
288
289
290
291
292 protected static class LinkMapIterator<K, V> extends LinkIterator<K, V> implements
293 OrderedMapIterator<K, V>, ResettableIterator<K> {
294
295
296
297
298
299
300 protected LinkMapIterator(final AbstractLinkedMap<K, V> parent) {
301 super(parent);
302 }
303
304 @Override
305 public K getKey() {
306 final LinkEntry<K, V> current = currentEntry();
307 if (current == null) {
308 throw new IllegalStateException(GETKEY_INVALID);
309 }
310 return current.getKey();
311 }
312
313 @Override
314 public V getValue() {
315 final LinkEntry<K, V> current = currentEntry();
316 if (current == null) {
317 throw new IllegalStateException(GETVALUE_INVALID);
318 }
319 return current.getValue();
320 }
321
322 @Override
323 public K next() {
324 return super.nextEntry().getKey();
325 }
326
327 @Override
328 public K previous() {
329 return super.previousEntry().getKey();
330 }
331
332 @Override
333 public V setValue(final V value) {
334 final LinkEntry<K, V> current = currentEntry();
335 if (current == null) {
336 throw new IllegalStateException(SETVALUE_INVALID);
337 }
338 return current.setValue(value);
339 }
340 }
341
342
343
344
345
346
347 protected static class ValuesIterator<V> extends LinkIterator<Object, V> implements
348 OrderedIterator<V>, ResettableIterator<V> {
349
350
351
352
353
354
355 @SuppressWarnings("unchecked")
356 protected ValuesIterator(final AbstractLinkedMap<?, V> parent) {
357 super((AbstractLinkedMap<Object, V>) parent);
358 }
359
360 @Override
361 public V next() {
362 return super.nextEntry().getValue();
363 }
364
365 @Override
366 public V previous() {
367 return super.previousEntry().getValue();
368 }
369 }
370
371
372 transient LinkEntry<K, V> header;
373
374
375
376
377 protected AbstractLinkedMap() {
378 }
379
380
381
382
383
384
385
386 protected AbstractLinkedMap(final int initialCapacity) {
387 super(initialCapacity);
388 }
389
390
391
392
393
394
395
396
397
398
399 protected AbstractLinkedMap(final int initialCapacity, final float loadFactor) {
400 super(initialCapacity, loadFactor);
401 }
402
403
404
405
406
407
408
409
410 protected AbstractLinkedMap(final int initialCapacity, final float loadFactor, final int threshold) {
411 super(initialCapacity, loadFactor, threshold);
412 }
413
414
415
416
417
418
419
420 protected AbstractLinkedMap(final Map<? extends K, ? extends V> map) {
421 super(map);
422 }
423
424
425
426
427
428
429
430
431
432
433
434 @Override
435 protected void addEntry(final HashEntry<K, V> entry, final int hashIndex) {
436 final LinkEntry<K, V> link = (LinkEntry<K, V>) entry;
437 link.after = header;
438 link.before = header.before;
439 header.before.after = link;
440 header.before = link;
441 data[hashIndex] = link;
442 }
443
444
445
446
447
448 @Override
449 public void clear() {
450
451 super.clear();
452 header.before = header.after = header;
453 }
454
455
456
457
458
459
460
461 @Override
462 public boolean containsValue(final Object value) {
463
464 if (value == null) {
465 for (LinkEntry<K, V> entry = header.after; entry != header; entry = entry.after) {
466 if (entry.getValue() == null) {
467 return true;
468 }
469 }
470 } else {
471 for (LinkEntry<K, V> entry = header.after; entry != header; entry = entry.after) {
472 if (isEqualValue(value, entry.getValue())) {
473 return true;
474 }
475 }
476 }
477 return false;
478 }
479
480
481
482
483
484
485
486
487
488
489
490
491
492 @Override
493 protected LinkEntry<K, V> createEntry(final HashEntry<K, V> next, final int hashCode, final K key, final V value) {
494 return new LinkEntry<>(next, hashCode, convertKey(key), value);
495 }
496
497
498
499
500
501
502
503 @Override
504 protected Iterator<Map.Entry<K, V>> createEntrySetIterator() {
505 if (isEmpty()) {
506 return EmptyOrderedIterator.<Map.Entry<K, V>>emptyOrderedIterator();
507 }
508 return new EntrySetIterator<>(this);
509 }
510
511
512
513
514
515
516
517 @Override
518 protected Iterator<K> createKeySetIterator() {
519 if (isEmpty()) {
520 return EmptyOrderedIterator.<K>emptyOrderedIterator();
521 }
522 return new KeySetIterator<>(this);
523 }
524
525
526
527
528
529
530
531 @Override
532 protected Iterator<V> createValuesIterator() {
533 if (isEmpty()) {
534 return EmptyOrderedIterator.<V>emptyOrderedIterator();
535 }
536 return new ValuesIterator<>(this);
537 }
538
539
540
541
542
543
544
545
546
547
548 protected LinkEntry<K, V> entryAfter(final LinkEntry<K, V> entry) {
549 return entry.after;
550 }
551
552
553
554
555
556
557
558
559
560
561 protected LinkEntry<K, V> entryBefore(final LinkEntry<K, V> entry) {
562 return entry.before;
563 }
564
565
566
567
568
569
570 @Override
571 public K firstKey() {
572 if (size == 0) {
573 throw new NoSuchElementException("Map is empty");
574 }
575 return header.after.getKey();
576 }
577
578
579
580
581
582
583
584
585 protected LinkEntry<K, V> getEntry(final int index) {
586 if (index < 0) {
587 throw new IndexOutOfBoundsException("Index " + index + " is less than zero");
588 }
589 if (index >= size) {
590 throw new IndexOutOfBoundsException("Index " + index + " is invalid for size " + size);
591 }
592 LinkEntry<K, V> entry;
593 if (index < size / 2) {
594
595 entry = header.after;
596 for (int currentIndex = 0; currentIndex < index; currentIndex++) {
597 entry = entry.after;
598 }
599 } else {
600
601 entry = header;
602 for (int currentIndex = size; currentIndex > index; currentIndex--) {
603 entry = entry.before;
604 }
605 }
606 return entry;
607 }
608
609 @Override
610 protected LinkEntry<K, V> getEntry(final Object key) {
611 return (LinkEntry<K, V>) super.getEntry(key);
612 }
613
614
615
616
617
618
619
620
621
622 @Override
623 protected void init() {
624 header = createEntry(null, -1, null, null);
625 header.before = header.after = header;
626 }
627
628
629
630
631
632
633 @Override
634 public K lastKey() {
635 if (size == 0) {
636 throw new NoSuchElementException("Map is empty");
637 }
638 return header.before.getKey();
639 }
640
641
642
643
644 @Override
645 public OrderedMapIterator<K, V> mapIterator() {
646 if (size == 0) {
647 return EmptyOrderedMapIterator.<K, V>emptyOrderedMapIterator();
648 }
649 return new LinkMapIterator<>(this);
650 }
651
652
653
654
655
656
657
658 @Override
659 public K nextKey(final Object key) {
660 final LinkEntry<K, V> entry = getEntry(key);
661 return entry == null || entry.after == header ? null : entry.after.getKey();
662 }
663
664
665
666
667
668
669
670 @Override
671 public K previousKey(final Object key) {
672 final LinkEntry<K, V> entry = getEntry(key);
673 return entry == null || entry.before == header ? null : entry.before.getKey();
674 }
675
676
677
678
679
680
681
682
683
684
685
686
687 @Override
688 protected void removeEntry(final HashEntry<K, V> entry, final int hashIndex, final HashEntry<K, V> previous) {
689 final LinkEntry<K, V> link = (LinkEntry<K, V>) entry;
690 link.before.after = link.after;
691 link.after.before = link.before;
692 link.after = null;
693 link.before = null;
694 super.removeEntry(entry, hashIndex, previous);
695 }
696
697 }