何时在 LinkedList 或 ArrayList 上使用 HashMap,反之亦然
Posted
技术标签:
【中文标题】何时在 LinkedList 或 ArrayList 上使用 HashMap,反之亦然【英文标题】:When to use HashMap over LinkedList or ArrayList and vice-versa 【发布时间】:2011-12-20 00:29:58 【问题描述】:为什么我们不能总是使用 HashMap,尽管它在添加、删除操作方面比 ArrayList 或 LinkedList 效率高得多,而且与元素的数量无关。
我google了一下,找到了一些原因,但是使用HashMap总是有一种解决方法,优势仍然存在。
【问题讨论】:
Lists
和 Maps
是两个完全不同的数据结构,具有不同的操作和不变量。您能否解释一下您认为两者都是可接受的解决方案的上下文/要求?
显然您从来不需要按特定顺序保存一组东西 ...
投反对票,为什么?我认为这是一个恰当的问题。虽然显示缺乏知识,但在 SO 问题上不应因显示缺乏知识而被否决。事实上,问题总是缺乏知识的结果。
【参考方案1】:
列表表示元素的顺序排列。 Maps 用于表示键/值对的集合。
虽然您可以将地图用作列表,但这样做有一些明显的缺点。
维护秩序: - 根据定义,列表是有序的。您添加项目,然后您可以按照插入项目的顺序遍历列表。当您将项目添加到 HashMap 时,不能保证按照放入它们的相同顺序检索项目。HashMap 的子类(如 LinkedHashMap)将保持顺序,但一般来说,Map 不能保证顺序。
键/值语义: - 映射的目的是根据可用于稍后检索项目的键来存储项目。只有在键恰好是列表中的位置的有限情况下,才能通过列表实现类似的功能。
代码可读性 考虑以下示例。
// Adding to a List
list.add(myObject); // adds to the end of the list
map.put(myKey, myObject); // sure, you can do this, but what is myKey?
map.put("1", myObject); // you could use the position as a key but why?
// Iterating through the items
for (Object o : myList) // nice and easy
for (Object o : myMap.values()) // more code and the order is not guaranteed
收集功能 一些很棒的实用功能可通过 Collections 类用于列表。比如……
// Randomize the list
Collections.shuffle(myList);
// Sort the list
Collections.sort(myList, myComparator);
希望对你有帮助,
【讨论】:
LinkedLists 由于性能问题经常被认为是不好的。由于元素排序,我经常使用 LinkedLists 而不是 ArrayLists。如果我使用带有位置作为键的 HashMaps 会更好(性能和内存)吗?【参考方案2】:列表和地图是不同的数据结构。当您想要将键与值相关联并且列表是有序集合时,使用映射。
Map 是 Java Collection Framework 中的一个接口,而 HashMap 是 Map 接口的一种实现。 HashMap 对于基于键定位值以及基于键插入和删除值是有效的。 HashMap 的条目没有排序。
ArrayList 和 LinkedList 是 List 接口的实现。 LinkedList 提供顺序访问,通常在插入和删除列表中的元素时效率更高,但是在访问列表中的元素时效率较低。 ArrayList 提供随机访问,在访问元素时效率更高,但在插入和删除元素时通常较慢。
【讨论】:
【参考方案3】:我会在这里放一些真实的案例和场景,什么时候使用一个或另一个,它可能对其他人有帮助:
HashMap
当您必须在应用程序中使用缓存时。 Redis 和 membase 是某种扩展的 HashMap。 (元素的顺序无关紧要,您需要快速( O(1) )读取访问(一个值),使用一个键)。
链表
当顺序很重要时(它们在添加到 LinkedList 时按顺序排列),元素的数量是未知的(不要浪费内存分配)并且您需要快速插入时间 ( O(1) )。可以在添加时按顺序列出的待办事项列表就是一个很好的例子。
【讨论】:
【参考方案4】:ArrayList 和 LinkedList 的缺点在于,在遍历它们时,根据搜索算法,查找项所需的时间会随着列表的大小而增长。
散列的美妙之处在于,尽管您牺牲了一些额外的时间来搜索元素,但所花费的时间并不会随着地图的大小而增加。这是因为 HashMap 通过将要搜索的元素直接转换为索引来查找信息,因此可以进行跳转。
长话短说... LinkedList:比ArrayList消耗更多内存,插入成本低(添加和删除) ArrayList:占用内存少,但与LinkedList类似,较大时搜索时间较长。 HashMap:可以跳转到值,使得大地图的搜索时间不变。与小列表相比,消耗更多内存并花费更长的时间来查找值。
【讨论】:
以上是关于何时在 LinkedList 或 ArrayList 上使用 HashMap,反之亦然的主要内容,如果未能解决你的问题,请参考以下文章
何时在 Java 中使用 LinkedList 而不是 ArrayList?
JDK1.8JDK1.8集合源码阅读——LinkedList