| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * This class represents a pair of two objects, used by LinkedHashMap | |
| 7 * to store a {key, value} in a list. | |
| 8 */ | |
| 9 class KeyValuePair<K, V> { | |
| 10 KeyValuePair(this.key, this.value) {} | |
| 11 | |
| 12 final K key; | |
| 13 V value; | |
| 14 } | |
| 15 | |
| 16 /** | |
| 17 * A LinkedHashMap is a hash map that preserves the insertion order | |
| 18 * when iterating over the keys or the values. Updating the value of a | |
| 19 * key does not change the order. | |
| 20 */ | |
| 21 class LinkedHashMapImplementation<K extends Hashable, V> | |
| 22 implements LinkedHashMap<K, V> { | |
| 23 DoubleLinkedQueue<KeyValuePair<K, V>> _list; | |
| 24 HashMap<K, DoubleLinkedQueueEntry<KeyValuePair<K, V>>> _map; | |
| 25 | |
| 26 LinkedHashMapImplementation() { | |
| 27 _map = new HashMap<K, DoubleLinkedQueueEntry<KeyValuePair<K, V>>>(); | |
| 28 _list = new DoubleLinkedQueue<KeyValuePair<K, V>>(); | |
| 29 } | |
| 30 | |
| 31 factory LinkedHashMapImplementation.from(Map<K, V> other) { | |
| 32 Map<K, V> result = new LinkedHashMapImplementation<K, V>(); | |
| 33 other.forEach((K key, V value) { result[key] = value; }); | |
| 34 return result; | |
| 35 } | |
| 36 | |
| 37 void operator []=(K key, V value) { | |
| 38 if (_map.containsKey(key)) { | |
| 39 _map[key].element.value = value; | |
| 40 } else { | |
| 41 _list.addLast(new KeyValuePair<K, V>(key, value)); | |
| 42 _map[key] = _list.lastEntry(); | |
| 43 } | |
| 44 } | |
| 45 | |
| 46 V operator [](K key) { | |
| 47 DoubleLinkedQueueEntry<KeyValuePair<K, V>> entry = _map[key]; | |
| 48 if (entry === null) return null; | |
| 49 return entry.element.value; | |
| 50 } | |
| 51 | |
| 52 V remove(K key) { | |
| 53 DoubleLinkedQueueEntry<KeyValuePair<K, V>> entry = _map.remove(key); | |
| 54 if (entry === null) return null; | |
| 55 entry.remove(); | |
| 56 return entry.element.value; | |
| 57 } | |
| 58 | |
| 59 V putIfAbsent(K key, V ifAbsent()) { | |
| 60 V value = this[key]; | |
| 61 if ((this[key] === null) && !(containsKey(key))) { | |
| 62 value = ifAbsent(); | |
| 63 this[key] = value; | |
| 64 } | |
| 65 return value; | |
| 66 } | |
| 67 | |
| 68 Collection<K> getKeys() { | |
| 69 List<K> list = new List<K>(length); | |
| 70 int index = 0; | |
| 71 _list.forEach(void _(KeyValuePair<K, V> entry) { | |
| 72 list[index++] = entry.key; | |
| 73 }); | |
| 74 assert(index == length); | |
| 75 return list; | |
| 76 } | |
| 77 | |
| 78 | |
| 79 Collection<V> getValues() { | |
| 80 List<V> list = new List<V>(length); | |
| 81 int index = 0; | |
| 82 _list.forEach(void _(KeyValuePair<K, V> entry) { | |
| 83 list[index++] = entry.value; | |
| 84 }); | |
| 85 assert(index == length); | |
| 86 return list; | |
| 87 } | |
| 88 | |
| 89 void forEach(void f(K key, V value)) { | |
| 90 _list.forEach(void _(KeyValuePair<K, V> entry) { | |
| 91 f(entry.key, entry.value); | |
| 92 }); | |
| 93 } | |
| 94 | |
| 95 bool containsKey(K key) { | |
| 96 return _map.containsKey(key); | |
| 97 } | |
| 98 | |
| 99 bool containsValue(V value) { | |
| 100 return _list.some(bool _(KeyValuePair<K, V> entry) { | |
| 101 return (entry.value == value); | |
| 102 }); | |
| 103 } | |
| 104 | |
| 105 int get length() { | |
| 106 return _map.length; | |
| 107 } | |
| 108 | |
| 109 bool isEmpty() { | |
| 110 return length == 0; | |
| 111 } | |
| 112 | |
| 113 void clear() { | |
| 114 _map.clear(); | |
| 115 _list.clear(); | |
| 116 } | |
| 117 | |
| 118 String toString() { | |
| 119 return Maps.mapToString(this); | |
| 120 } | |
| 121 } | |
| OLD | NEW |