为什么LinkedHashMap不提供索引访问?

时间:2011-04-14 16:59:56

标签: java linkedhashmap

来自Javadoc:
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries.

如果是这样,那为什么它不提供像java中的List这样的对象访问, list.get(索引);

更新

我使用LinkedHashMap实现了LRU Cache。我的算法要求我从缓存中访问LRU对象。这就是为什么我需要随机访问,但我认为这会让我失去性能,所以我改变了逻辑,我正在访问LRU对象就在Cache已满时...使用removeEldestEntry()

谢谢大家...

6 个答案:

答案 0 :(得分:15)

a)因为条目已关联,因此无法随机访问。如果我没有错误,表现会很糟糕,O(N)

b)因为没有用于备份此功能的界面。因此,选择是为此引入专用接口(性能不佳)或要求客户端针对实现类而不是接口进行编程


顺便提一句Guava,有一个简单的解决方案:

Iterables.get(map.values(), offset);

对于缓存,请查看Guava的MapMaker及其过期功能。

答案 1 :(得分:7)

由于values()提供值的后备集合,您可以这样解决:

map.values().remove(map.values().toArray()[index]);

也许不是非常有效(特别是在内存方面),但它应该像你期望的那样O(N)


顺便说一下,我认为这个问题对于所有List操作都是合法的。 (不管怎样,它不应该比LinkedList慢,对吧?)

我开始执行LinkedHashMapList扩展LinkedHashMap并实现List接口。令人惊讶的是,由于删除冲突,似乎无法做到。现有remove方法返回先前映射的对象,而List.remove应返回boolean

这只是一个反思,老实说,我也觉得令人讨厌LinkedHashMap不能被视为LinkedList

答案 2 :(得分:3)

答案 3 :(得分:1)

它提供了一个Iterator接口,列表中的每个节点都链接到它之前和之后的节点。使用get(i)方法与迭代列表中的所有元素没有什么不同,因为没有后备数组(与LinkedList相同)。

如果你需要这种不太高效的能力,我建议你自己扩展地图

答案 4 :(得分:1)

如果您想随机访问,可以

Map<K,V> map = new LinkedHashMap<K,V>();
Map.Entry<K,V>[] entries = (Map.Entry<K,V>[]) map.toArray(new Map.Entry[map.size()]);
Map.Entry<K,V> entry_n = entry[n];

正如您所看到的,除非您缓存entries数组,否则性能可能会非常差。

但我会质疑它的必要性。

答案 5 :(得分:0)

通过索引创建具有log(N)访问效率的Map是没有实际问题的。如果您使用红黑树并为每个节点存储从该节点开始的树中元素的数量,则可以编写log(N)的get(int index)方法。