我打算使用Hashtable
,但一些现有的答案说只有LinkedHashMap
保留插入顺序。因此,我似乎可以通过entries
或keys
属性获得插入顺序。
我的问题是,当映射有n个元素时,如果我想删除前n/2个元素,是否有比循环通过keys
并反复调用remove(key)
更好的方法?也就是像这样的
val a = LinkedHashMap<Int, Int>();
val n = 10;
for(i in 1 .. n)
{
a[i] = i*10;
}
a.removeRange(0,n/2);
不是
val a = LinkedHashMap<Int, Int>();
val n = 10;
for(i in 1 .. n)
{
a[i] = i*10;
}
var i = 0;
var keysToRemove= ArrayList<Int>();
for(k in a.keys)
{
if(i >= n/2)
break;
else
i++
keysToRemove.add(k);
}
for(k in keysToRemove)
{
a.remove(k);
}
这样做的目的是我将映射用作缓存,当缓存已满时,我希望清除最老的那一半条目。我不必使用LinkedHashMap
,只要我可以:
- 使用键查找值,高效。
- 一次删除一系列条目。
类中没有方法可以实现这一点。源代码没有对键或项的范围进行任何操作。由于链接是建立在HashMap逻辑之上的,单个条目仍然必须通过散列键查找来单独找到以删除它们,因此在LinkedHashMap中删除范围的速度不能更快,这与LinkedList与ArrayList的类比不同。
对于更简单的代码,这相当于你所做的:
a.keys.take(a.size / 2).forEach(a::remove)
如果你不想为缓存集使用库,LinkedHashSet的设计使你可以通过子类化轻松地构建自己的缓存集。例如,当添加超过一定集合大小的元素时,一个基本的方法只是删除最老的条目:
class CacheHashMap<K, V>(private var maxSize: Int): LinkedHashMap<K, V>() {
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean =
size == maxSize
}
同样,如果您在构造函数调用中设置accessOrder
为true,它将按最近使用的条目排序,这可能比插入顺序更适合您的情况。
编辑:对不起,我错过了使用这个作为LRU缓存的部分,对于那个用例,TreeMap将不适合。
如果插入顺序对您来说只是偶然的,并且您想要的实际上是可比较键的实际顺序,那么您应该使用TreeMap。
但是,可能不直接支持删除一半键的特定用例。您应该找到方法来删除低于/高于某个值的键,并获得最高/最低的键。