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.io.IOException;
20 import java.io.ObjectInputStream;
21 import java.io.ObjectOutputStream;
22 import java.io.Serializable;
23 import java.util.AbstractList;
24 import java.util.AbstractSet;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.ListIterator;
31 import java.util.Map;
32 import java.util.NoSuchElementException;
33 import java.util.Set;
34
35 import org.apache.commons.collections4.OrderedMap;
36 import org.apache.commons.collections4.OrderedMapIterator;
37 import org.apache.commons.collections4.ResettableIterator;
38 import org.apache.commons.collections4.iterators.AbstractUntypedIteratorDecorator;
39 import org.apache.commons.collections4.keyvalue.AbstractMapEntry;
40 import org.apache.commons.collections4.list.UnmodifiableList;
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public class ListOrderedMap<K, V>
85 extends AbstractMapDecorator<K, V>
86 implements OrderedMap<K, V>, Serializable {
87
88 static class EntrySetView<K, V> extends AbstractSet<Map.Entry<K, V>> {
89 private final ListOrderedMap<K, V> parent;
90 private final List<K> insertOrder;
91 private Set<Map.Entry<K, V>> entrySet;
92
93 EntrySetView(final ListOrderedMap<K, V> parent, final List<K> insertOrder) {
94 this.parent = parent;
95 this.insertOrder = insertOrder;
96 }
97
98 @Override
99 public void clear() {
100 parent.clear();
101 }
102
103 @Override
104 public boolean contains(final Object obj) {
105 return getEntrySet().contains(obj);
106 }
107 @Override
108 public boolean containsAll(final Collection<?> coll) {
109 return getEntrySet().containsAll(coll);
110 }
111
112 @Override
113 public boolean equals(final Object obj) {
114 if (obj == this) {
115 return true;
116 }
117 return getEntrySet().equals(obj);
118 }
119
120 private Set<Map.Entry<K, V>> getEntrySet() {
121 if (entrySet == null) {
122 entrySet = parent.decorated().entrySet();
123 }
124 return entrySet;
125 }
126
127 @Override
128 public int hashCode() {
129 return getEntrySet().hashCode();
130 }
131
132 @Override
133 public boolean isEmpty() {
134 return parent.isEmpty();
135 }
136
137 @Override
138 public Iterator<Map.Entry<K, V>> iterator() {
139 return new ListOrderedIterator<>(parent, insertOrder);
140 }
141
142 @Override
143 @SuppressWarnings("unchecked")
144 public boolean remove(final Object obj) {
145 if (!(obj instanceof Map.Entry)) {
146 return false;
147 }
148 if (getEntrySet().contains(obj)) {
149 final Object key = ((Map.Entry<K, V>) obj).getKey();
150 parent.remove(key);
151 return true;
152 }
153 return false;
154 }
155
156 @Override
157 public int size() {
158 return parent.size();
159 }
160
161 @Override
162 public String toString() {
163 return getEntrySet().toString();
164 }
165 }
166
167 static class KeySetView<K> extends AbstractSet<K> {
168 private final ListOrderedMap<K, Object> parent;
169
170 @SuppressWarnings("unchecked")
171 KeySetView(final ListOrderedMap<K, ?> parent) {
172 this.parent = (ListOrderedMap<K, Object>) parent;
173 }
174
175 @Override
176 public void clear() {
177 parent.clear();
178 }
179
180 @Override
181 public boolean contains(final Object value) {
182 return parent.containsKey(value);
183 }
184
185 @Override
186 public Iterator<K> iterator() {
187 return new AbstractUntypedIteratorDecorator<Map.Entry<K, Object>, K>(parent.entrySet().iterator()) {
188 @Override
189 public K next() {
190 return getIterator().next().getKey();
191 }
192 };
193 }
194
195 @Override
196 public int size() {
197 return parent.size();
198 }
199 }
200
201 static class ListOrderedIterator<K, V> extends AbstractUntypedIteratorDecorator<K, Map.Entry<K, V>> {
202 private final ListOrderedMap<K, V> parent;
203 private K last;
204
205 ListOrderedIterator(final ListOrderedMap<K, V> parent, final List<K> insertOrder) {
206 super(insertOrder.iterator());
207 this.parent = parent;
208 }
209
210 @Override
211 public Map.Entry<K, V> next() {
212 last = getIterator().next();
213 return new ListOrderedMapEntry<>(parent, last);
214 }
215
216 @Override
217 public void remove() {
218 super.remove();
219 parent.decorated().remove(last);
220 }
221 }
222
223 static class ListOrderedMapEntry<K, V> extends AbstractMapEntry<K, V> {
224 private final ListOrderedMap<K, V> parent;
225
226 ListOrderedMapEntry(final ListOrderedMap<K, V> parent, final K key) {
227 super(key, null);
228 this.parent = parent;
229 }
230
231 @Override
232 public V getValue() {
233 return parent.get(getKey());
234 }
235
236 @Override
237 public V setValue(final V value) {
238 return parent.decorated().put(getKey(), value);
239 }
240 }
241
242 static class ListOrderedMapIterator<K, V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
243 private final ListOrderedMap<K, V> parent;
244 private ListIterator<K> iterator;
245 private K last;
246 private boolean readable;
247
248 ListOrderedMapIterator(final ListOrderedMap<K, V> parent) {
249 this.parent = parent;
250 this.iterator = parent.insertOrder.listIterator();
251 }
252
253 @Override
254 public K getKey() {
255 if (!readable) {
256 throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
257 }
258 return last;
259 }
260
261 @Override
262 public V getValue() {
263 if (!readable) {
264 throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
265 }
266 return parent.get(last);
267 }
268
269 @Override
270 public boolean hasNext() {
271 return iterator.hasNext();
272 }
273
274 @Override
275 public boolean hasPrevious() {
276 return iterator.hasPrevious();
277 }
278
279 @Override
280 public K next() {
281 last = iterator.next();
282 readable = true;
283 return last;
284 }
285
286 @Override
287 public K previous() {
288 last = iterator.previous();
289 readable = true;
290 return last;
291 }
292
293 @Override
294 public void remove() {
295 if (!readable) {
296 throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
297 }
298 iterator.remove();
299 parent.map.remove(last);
300 readable = false;
301 }
302
303 @Override
304 public void reset() {
305 iterator = parent.insertOrder.listIterator();
306 last = null;
307 readable = false;
308 }
309
310 @Override
311 public V setValue(final V value) {
312 if (!readable) {
313 throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
314 }
315 return parent.map.put(last, value);
316 }
317
318 @Override
319 public String toString() {
320 if (readable) {
321 return "Iterator[" + getKey() + "=" + getValue() + "]";
322 }
323 return "Iterator[]";
324 }
325 }
326
327 static class ValuesView<V> extends AbstractList<V> {
328 private final ListOrderedMap<Object, V> parent;
329
330 @SuppressWarnings("unchecked")
331 ValuesView(final ListOrderedMap<?, V> parent) {
332 this.parent = (ListOrderedMap<Object, V>) parent;
333 }
334
335 @Override
336 public void clear() {
337 parent.clear();
338 }
339
340 @Override
341 public boolean contains(final Object value) {
342 return parent.containsValue(value);
343 }
344
345 @Override
346 public V get(final int index) {
347 return parent.getValue(index);
348 }
349
350 @Override
351 public Iterator<V> iterator() {
352 return new AbstractUntypedIteratorDecorator<Map.Entry<Object, V>, V>(parent.entrySet().iterator()) {
353 @Override
354 public V next() {
355 return getIterator().next().getValue();
356 }
357 };
358 }
359
360 @Override
361 public V remove(final int index) {
362 return parent.remove(index);
363 }
364
365 @Override
366 public V set(final int index, final V value) {
367 return parent.setValue(index, value);
368 }
369
370 @Override
371 public int size() {
372 return parent.size();
373 }
374 }
375
376
377 private static final long serialVersionUID = 2728177751851003750L;
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392 public static <K, V> ListOrderedMap<K, V> listOrderedMap(final Map<K, V> map) {
393 return new ListOrderedMap<>(map);
394 }
395
396
397 private final List<K> insertOrder = new ArrayList<>();
398
399
400
401
402
403
404
405 public ListOrderedMap() {
406 this(new HashMap<>());
407 }
408
409
410
411
412
413
414
415 protected ListOrderedMap(final Map<K, V> map) {
416 super(map);
417 insertOrder.addAll(decorated().keySet());
418 }
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439 public List<K> asList() {
440 return keyList();
441 }
442
443 @Override
444 public void clear() {
445 decorated().clear();
446 insertOrder.clear();
447 }
448
449
450
451
452
453
454
455
456
457 @Override
458 public Set<Map.Entry<K, V>> entrySet() {
459 return new EntrySetView<>(this, insertOrder);
460 }
461
462
463
464
465
466
467
468 @Override
469 public K firstKey() {
470 if (isEmpty()) {
471 throw new NoSuchElementException("Map is empty");
472 }
473 return insertOrder.get(0);
474 }
475
476
477
478
479
480
481
482
483 public K get(final int index) {
484 return insertOrder.get(index);
485 }
486
487
488
489
490
491
492
493
494 public V getValue(final int index) {
495 return get(insertOrder.get(index));
496 }
497
498
499
500
501
502
503
504 public int indexOf(final Object key) {
505 return insertOrder.indexOf(key);
506 }
507
508
509
510
511
512
513
514
515
516
517
518
519 public List<K> keyList() {
520 return UnmodifiableList.unmodifiableList(insertOrder);
521 }
522
523
524
525
526
527
528
529
530
531
532 @Override
533 public Set<K> keySet() {
534 return new KeySetView<>(this);
535 }
536
537
538
539
540
541
542
543 @Override
544 public K lastKey() {
545 if (isEmpty()) {
546 throw new NoSuchElementException("Map is empty");
547 }
548 return insertOrder.get(size() - 1);
549 }
550
551 @Override
552 public OrderedMapIterator<K, V> mapIterator() {
553 return new ListOrderedMapIterator<>(this);
554 }
555
556
557
558
559
560
561
562
563 @Override
564 public K nextKey(final Object key) {
565 final int index = insertOrder.indexOf(key);
566 if (index >= 0 && index < size() - 1) {
567 return insertOrder.get(index + 1);
568 }
569 return null;
570 }
571
572
573
574
575
576
577
578
579 @Override
580 public K previousKey(final Object key) {
581 final int index = insertOrder.indexOf(key);
582 if (index > 0) {
583 return insertOrder.get(index - 1);
584 }
585 return null;
586 }
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609 public V put(int index, final K key, final V value) {
610 if (index < 0 || index > insertOrder.size()) {
611 throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + insertOrder.size());
612 }
613
614 final Map<K, V> m = decorated();
615 if (m.containsKey(key)) {
616 final V result = m.remove(key);
617 final int pos = insertOrder.indexOf(key);
618 insertOrder.remove(pos);
619 if (pos < index) {
620 index--;
621 }
622 insertOrder.add(index, key);
623 m.put(key, value);
624 return result;
625 }
626 insertOrder.add(index, key);
627 m.put(key, value);
628 return null;
629 }
630
631 @Override
632 public V put(final K key, final V value) {
633 if (decorated().containsKey(key)) {
634
635 return decorated().put(key, value);
636 }
637
638 final V result = decorated().put(key, value);
639 insertOrder.add(key);
640 return result;
641 }
642
643
644
645
646
647
648
649
650
651 public void putAll(int index, final Map<? extends K, ? extends V> map) {
652 if (index < 0 || index > insertOrder.size()) {
653 throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + insertOrder.size());
654 }
655 for (final Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
656 final K key = entry.getKey();
657 final boolean contains = containsKey(key);
658
659
660 put(index, entry.getKey(), entry.getValue());
661 if (!contains) {
662
663 index++;
664 } else {
665
666 index = indexOf(entry.getKey()) + 1;
667 }
668 }
669 }
670
671 @Override
672 public void putAll(final Map<? extends K, ? extends V> map) {
673 for (final Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
674 put(entry.getKey(), entry.getValue());
675 }
676 }
677
678
679
680
681
682
683
684
685
686 @SuppressWarnings("unchecked")
687 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
688 in.defaultReadObject();
689 map = (Map<K, V>) in.readObject();
690 }
691
692
693
694
695
696
697
698
699 public V remove(final int index) {
700 return remove(get(index));
701 }
702
703 @Override
704 public V remove(final Object key) {
705 V result = null;
706 if (decorated().containsKey(key)) {
707 result = decorated().remove(key);
708 insertOrder.remove(key);
709 }
710 return result;
711 }
712
713
714
715
716
717
718
719
720
721
722 public V setValue(final int index, final V value) {
723 final K key = insertOrder.get(index);
724 return put(key, value);
725 }
726
727
728
729
730
731
732 @Override
733 public String toString() {
734 if (isEmpty()) {
735 return "{}";
736 }
737 final StringBuilder buf = new StringBuilder();
738 buf.append('{');
739 boolean first = true;
740 for (final Map.Entry<K, V> entry : entrySet()) {
741 final K key = entry.getKey();
742 final V value = entry.getValue();
743 if (first) {
744 first = false;
745 } else {
746 buf.append(", ");
747 }
748 buf.append(key == this ? "(this Map)" : key);
749 buf.append('=');
750 buf.append(value == this ? "(this Map)" : value);
751 }
752 buf.append('}');
753 return buf.toString();
754 }
755
756
757
758
759
760
761
762
763
764
765
766
767 public List<V> valueList() {
768 return new ValuesView<>(this);
769 }
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784 @Override
785 public Collection<V> values() {
786 return new ValuesView<>(this);
787 }
788
789
790
791
792
793
794
795
796 private void writeObject(final ObjectOutputStream out) throws IOException {
797 out.defaultWriteObject();
798 out.writeObject(map);
799 }
800
801 }