3cf5d6531d
BUG= Review URL: https://chromiumcodereview.appspot.com//10890030 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@11606 260f80e4-7a28-3924-810f-c04153c831b5
122 lines
2.9 KiB
Dart
122 lines
2.9 KiB
Dart
// 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 extends Hashable, 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);
|
|
}
|
|
}
|