如果LinkedHashMap的时间复杂度与HashMap的复杂度相同,为什么还需要HashMap?与Java中的HashMap相比,LinkedHashMap有哪些额外开销?
如果LinkedHashMap的时间复杂度与HashMap的复杂度相同,为什么还需要HashMap?与Java中的HashMap相比,LinkedHashMap有哪些额外开销?
LinkedHashMap会占用更多的内存。在普通的HashMap
中,每个条目只有键和值。而每个LinkedHashMap
的条目除了键和值之外,还包括对下一个和前一个条目的引用。此外,还需要进行一些额外的管理工作,尽管这通常是不相关的。
如果LinkedHashMap的时间复杂度与HashMap相同,为什么我们还需要HashMap?
您不应将复杂度与性能混淆。两个算法可以具有相同的复杂度,但其中一个可能始终表现更好。
请记住,f(N)是O(N)
意味着:
limit(f(N), N -> infinity) <= C*N
其中 C
是一个常数。算法的复杂度并不代表 C
值大小的优劣。对于两个不同的算法,常量 C
很可能是不同的。
(还要记住,大O复杂度是关于当 N
变得非常大时的行为/性能。它并没有告诉你关于更小的 N
值的行为/性能。)
即便如此:
HashMap
和LinkedHashMap
等价使用情况下的性能差异相对较小。
LinkedHashMap
使用更多的内存。例如,Java 11实现在每个映射条目中具有两个额外的引用字段来表示之前/之后的列表。在64位平台上没有压缩OOPs的情况下,额外的开销为每个条目16字节。
相对较小的性能和/或内存使用差异实际上对那些对性能或内存至关重要的应用程序的人们来说可能很重要1。
1- ... 还有那些毫无必要地过分关注这些事情的人。
LinkedHashMap是一种有用的数据结构,当您需要了解键插入到Map的顺序时可以使用它。一个适当的用例是实现LRU缓存。由于LinkedHashMap维护顺序,相比于HashMap,该数据结构需要额外的内存。如果插入顺序不是必要的,则应始终选择HashMap。
HashMap
不维护插入顺序,因此也不维护任何双向链表。
LinkedHashMap
最显著的特点是它维护键值对的插入顺序。为了实现这一点,LinkedHashMap
使用双向链表。
LinkedHashMap
的条目看起来像这样:
static class Entry<K, V> {
K key;
V value;
Entry<K,V> next;
Entry<K,V> before, after; //For maintaining insertion order
public Entry(K key, V value, Entry<K,V> next){
this.key = key;
this.value = value;
this.next = next;
}
}
LinkedHashMap
中新添加的条目,这有助于我们维护插入顺序。LinkedHashMap
中的下一个条目。