blob: 37f31697d59aa433d847ded806bf09013d204e10 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/**
* This class represents a pair of two objects, used by LinkedHashMap
* to store a {key, value} in a list.
*/
class KeyValuePair<K, V> {
KeyValuePair(this.key, this.value) {}
final K key;
V value;
}
/**
* A LinkedHashMap is a hash map that preserves the insertion order
* when iterating over the keys or the values. Updating the value of a
* key does not change the order.
*/
class LinkedHashMapImplementation<K, V>
implements LinkedHashMap<K, V> {
DoubleLinkedQueue<KeyValuePair<K, V>> _list;
HashMap<K, DoubleLinkedQueueEntry<KeyValuePair<K, V>>> _map;
LinkedHashMapImplementation() {
_map = new HashMap<K, DoubleLinkedQueueEntry<KeyValuePair<K, V>>>();
_list = new DoubleLinkedQueue<KeyValuePair<K, V>>();
}
factory LinkedHashMapImplementation.from(Map<K, V> other) {
Map<K, V> result = new LinkedHashMapImplementation<K, V>();
other.forEach((K key, V value) { result[key] = value; });
return result;
}
void operator []=(K key, V value) {
if (_map.containsKey(key)) {
_map[key].element.value = value;
} else {
_list.addLast(new KeyValuePair<K, V>(key, value));
_map[key] = _list.lastEntry();
}
}
V operator [](K key) {
DoubleLinkedQueueEntry<KeyValuePair<K, V>> entry = _map[key];
if (entry === null) return null;
return entry.element.value;
}
V remove(K key) {
DoubleLinkedQueueEntry<KeyValuePair<K, V>> entry = _map.remove(key);
if (entry === null) return null;
entry.remove();
return entry.element.value;
}
V putIfAbsent(K key, V ifAbsent()) {
V value = this[key];
if ((this[key] === null) && !(containsKey(key))) {
value = ifAbsent();
this[key] = value;
}
return value;
}
Collection<K> getKeys() {
List<K> list = new List<K>(length);
int index = 0;
_list.forEach(void _(KeyValuePair<K, V> entry) {
list[index++] = entry.key;
});
assert(index == length);
return list;
}
Collection<V> getValues() {
List<V> list = new List<V>(length);
int index = 0;
_list.forEach(void _(KeyValuePair<K, V> entry) {
list[index++] = entry.value;
});
assert(index == length);
return list;
}
void forEach(void f(K key, V value)) {
_list.forEach(void _(KeyValuePair<K, V> entry) {
f(entry.key, entry.value);
});
}
bool containsKey(K key) {
return _map.containsKey(key);
}
bool containsValue(V value) {
return _list.some(bool _(KeyValuePair<K, V> entry) {
return (entry.value == value);
});
}
int get length {
return _map.length;
}
bool isEmpty() {
return length == 0;
}
void clear() {
_map.clear();
_list.clear();
}
String toString() {
return Maps.mapToString(this);
}
}