除了循环之外,删除 LinkedHashMap 中的前半部分条目
Removing the first half of the entries in LinkedHashMap other than looping
我打算使用 Hashtable
,但一些现有答案只说 LinkedHashMap
保留插入顺序。所以,我似乎可以通过 entries
或 keys
属性获得插入顺序。
我的问题是,当地图有 n 个元素时,如果我想删除第一个 n/2 个元素,有没有比遍历 keys
并重复调用 [=17] 更好的方法=]?也就是像这样
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
只要我能:
- 使用键高效地查找值。
- 一次删除一系列条目。
编辑:抱歉,我错过了关于将其用作 LRU 缓存的部分,对于该用例,TreeMap 不适合。
如果插入顺序对你来说只是偶然的,而你想要的实际上是可比较键的实际顺序,你应该改用 TreeMap。
但是,可能不直接支持删除一半密钥的特定用例。您宁愿找到删除键 below/above 特定值的方法,并获得 highest/lowest 键。
class 中没有方法可以做到这一点。源代码对键或条目的范围没有任何操作。由于链接建立在 HashMap 逻辑之上,单个条目仍然必须通过散列键查找单独找到以删除它们,因此在 LinkedHashMap 中无法更快地完成删除范围,这与LinkedList 与 ArrayList 的类比。
对于与您所做的等效的更简单的代码:
a.keys.take(a.size / 2).forEach(a::remove)
如果您不想为缓存集使用库,LinkedHashSet 的设计让您可以通过 subclassing 轻松构建自己的缓存集。例如,当您添加超过特定集合大小时的元素时,一个简单地删除最旧条目的基本方法:
class CacheHashMap<K, V>(private var maxSize: Int): LinkedHashMap<K, V>() {
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean =
size == maxSize
}
此外,如果您在构造函数调用中将 accessOrder
设置为 true,它会按最后使用到最近使用的条目排序,这可能比插入顺序更适合您的情况。
我打算使用 Hashtable
,但一些现有答案只说 LinkedHashMap
保留插入顺序。所以,我似乎可以通过 entries
或 keys
属性获得插入顺序。
我的问题是,当地图有 n 个元素时,如果我想删除第一个 n/2 个元素,有没有比遍历 keys
并重复调用 [=17] 更好的方法=]?也就是像这样
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
只要我能:
- 使用键高效地查找值。
- 一次删除一系列条目。
编辑:抱歉,我错过了关于将其用作 LRU 缓存的部分,对于该用例,TreeMap 不适合。
如果插入顺序对你来说只是偶然的,而你想要的实际上是可比较键的实际顺序,你应该改用 TreeMap。
但是,可能不直接支持删除一半密钥的特定用例。您宁愿找到删除键 below/above 特定值的方法,并获得 highest/lowest 键。
class 中没有方法可以做到这一点。源代码对键或条目的范围没有任何操作。由于链接建立在 HashMap 逻辑之上,单个条目仍然必须通过散列键查找单独找到以删除它们,因此在 LinkedHashMap 中无法更快地完成删除范围,这与LinkedList 与 ArrayList 的类比。
对于与您所做的等效的更简单的代码:
a.keys.take(a.size / 2).forEach(a::remove)
如果您不想为缓存集使用库,LinkedHashSet 的设计让您可以通过 subclassing 轻松构建自己的缓存集。例如,当您添加超过特定集合大小时的元素时,一个简单地删除最旧条目的基本方法:
class CacheHashMap<K, V>(private var maxSize: Int): LinkedHashMap<K, V>() {
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean =
size == maxSize
}
此外,如果您在构造函数调用中将 accessOrder
设置为 true,它会按最后使用到最近使用的条目排序,这可能比插入顺序更适合您的情况。