class MruList<of T> implements ICollection<of T>
"""
Store a "most recently used" list of items.
Calling .add puts the item at the front of the list.
Also, .add will not grow the list when it already contains a given item.
An MruList is enumerable, so you can use for loops on it, .toList, .numbered, .reversed, etc.
Because an MruList uses a dictionary internally for some caching, the item T should implement
both .equals and .getHashCode.
to-do: support a max capacity
"""
var _list = LinkedList<of T>()
var _dict = Dictionary<of T, LinkedListNode<of T>>()
def add(item as T)
if _list.count <= 4 # to-do: test what the real switchover should be
_list.remove(item)
else
lln as LinkedListNode<of T>?
if _dict.tryGetValue(item, out lln), _list.remove(lln)
_dict[item] = _list.addFirst(item) to !
assert _list.count == _dict.count
def clear
_list.clear
_dict.clear
assert _list.count == _dict.count
def contains(item as T) as bool
return _list.contains(item)
def copyTo(array as T[], arrayIndex as int)
_list.copyTo(array, arrayIndex)
get count as int
return _list.count
def getEnumerator as IEnumerator<of T>
return _list.getEnumerator
def getEnumerator as System.Collections.IEnumerator
implements System.Collections.IEnumerable
return .getEnumerator
get isReadOnly as bool
return false
def remove(item as T) as bool
_dict.remove(item)
r = _list.remove(item)
assert _list.count == _dict.count
return r
def set(items as IList<of T>)
"""
Set all the items in the MRU list.
There is no reversal of the items like if you called .add for each item.
Repeated items are forbidden and will cause an exception.
"""
.clear
for item in items, _dict[item] = _list.addLast(item) to !
if _dict.count <> _list.count, throw InvalidOperationException('repeated items in set list')
class TestMruList
test
ml = MruList<of String>()
assert ml.count == 0
ml.add('foo')
assert ml.count == 1
assert ml.contains('foo')
assert not ml.contains('bar')
assert ml.toList == ['foo']
ml.clear
assert ml.count == 0
ml = MruList<of String>()
ml.add('foo')
ml.add('bar')
assert ml.contains('foo')
assert ml.contains('bar')
assert ml.toList == ['bar', 'foo'] # note the mru order
ml.add('bar')
assert ml.toList == ['bar', 'foo']
ml.add('bar')
assert ml.toList == ['bar', 'foo']
ml.add('foo')
assert ml.toList == ['foo', 'bar']
ml.add('baz')
assert ml.toList == ['baz', 'foo', 'bar']
ml = MruList<of String>()
ml.set(['foo', 'bar', 'baz'])
assert ml.toList == ['foo', 'bar', 'baz']
ml.add('buzz')
assert ml.toList == ['buzz', 'foo', 'bar', 'baz']
ml.set(['foo', 'bar', 'baz'])
assert ml.toList == ['foo', 'bar', 'baz']
...Hmm that syntax highlighting doesn't look right.
Update 2011-09-05: Syntax highlighting fixed courtesy of Todd A.