我应该使用哪个Java集合?


127

在这个问题中,如何在C ++ 11中有效地选择标准库容器?是选择C ++集合时要使用的便捷流程图。

我认为对于那些不确定应该使用哪个集合的人来说,这是一个有用的资源,因此我试图找到类似的Java流程图,但未能做到。

哪些资源和“备忘单”可用来帮助人们选择使用Java进行编程时要使用的正确Collection?人们如何知道应该使用哪些List,Set和Map实现?


《 Java泛型和集合》(Naftalin和Wadler)一书对此进行了介绍。
Christophe Roussy

Answers:


292

由于找不到相似的流程图,我决定自己制作一个。

该流程图未尝试涵盖同步访问,线程安全性或旧版集合等内容,但确实涵盖了3个标准Set,3个标准Map和2个标准List

在此处输入图片说明

此图像是为此答案创建的,并根据知识共享署名4.0国际许可获得许可。最简单的归因是通过链接到此问题或此答案。

其他资源

可能最有用的其他参考是oracle文档的以下页面,该页面描述了每个Collection

HashSet与TreeSet

关于何时使用HashSetTreeSet在此处进行详细讨论: Hashset与Treeset

ArrayList与LinkedList

详细讨论:何时在ArrayList上使用LinkedList?


真好!但我必须不同意您的LinkedListvs ArrayList决定。首先,如果列表很大,LinkedList则是可取的。LinkedList具有每个元素的开销,因此就内存消耗而言,它的渐近性要比差ArrayList。同样,如果大多数访问都在列表的末尾,则an ArrayList是可取的,因为它提供了恒定时间的随机元素访问。访问a的nth元素LinkedList是一个O(n)操作。...实际上,使用链接列表的决定几乎总是 “不”。
马特·鲍尔

2
@MattBall我大部分时候都同意你的看法。但是Java LinkedList是一个双链表,因此开始和结束时的访问速度都很快。您会注意到,在我建议使用LinkedList- 之前,所有三个问题中的分支都必须回答“是” ,因此换句话说,我同意您的看法,在大多数情况下,答案为“否”。诸如队列和出队之类的事情,您需要不断地从列表区域的末端添加和删除事物,这是很好的用例LinkedList
Tim B

@MattBall内存使用情况更加棘手,因为LinkedList每个元素使用更多内存... ArrayList永远不会释放内存。这意味着,如果您的列表有时会变得很大,但通常很小,那么ArrayList内存性能就会下降。List与其本身所包含的元素相比,其自身的内存开销通常(尽管并不总是)较小。
Tim B

Map<K,V>不属于java.util.collection
Mehraj Malik '18

@MehrajMalik嗯,标签不明确,我同意。我的意思是java.util中的Collection。即java.util。*在此处插入集合名称*
Tim B

66

主要的非并发,非同步集合的摘要

Collection:表示无序的“袋”物品的接口,称为“元素”。“下一个”元素未定义(随机)。

  • Set:表示的接口Collection,没有重复项。
    • HashSetSetHashtable。当订购不重要时,最快和最小的内存使用情况。
    • LinkedHashSet:A,HashSet带有一个链接列表,以插入顺序关联元素。“下一个”元素是最近插入的元素。
    • TreeSet:,Set其中元素按Comparator(通常是自然排序排序。最慢和最大的内存使用情况,但对于基于比较器的排序是必需的。
    • EnumSetSet针对单个枚举类型的极其快速和高效的定制。
  • List:一个表示Collection的元素的接口,每个元素都有序,每个都有一个数字索引来表示其位置,其中第一个元素为零,(length - 1)最后一个元素。
    • ArrayListList由数组支持,其中数组的长度(称为“容量”)至少与元素数(列表的“大小”)一样大。当大小超出容量时((capacity + 1)-th添加元素时),将以新容量-重新创建阵列-这种重新创建(new length * 1.5)很快,因为它使用System.arrayCopy()。删除和插入/添加元素需要将所有相邻元素(在右侧)移入或移出该空间。访问任何元素都是快速的,因为只需要计算(element-zero-address + desired-index * element-size)即可找到其位置。在大多数情况下ArrayList优先于LinkedList
    • LinkedListList由一组对象支持,每个对象都链接到其“上一个”和“下一个”邻居。A LinkedList也是QueueDeque。从第一个或最后一个元素开始访问元素,然后遍历直到达到所需的索引。一旦通过遍历达到了所需的索引,插入和删除就变成了一个琐碎的事:仅重新映射直接邻居链接以指向新元素或绕过现在删除的元素。
  • Map:表示Collection每个元素都有一个标识“键”的接口,每个元素都是一个键值对。
    • HashMap:,Map其中的键是无序的,并带有Hashtable
    • LinkedhashMap:密钥按插入顺序排序
    • TreeMap:,Map其中键是按Comparator(通常是自然排序)排序的。
  • Queue:一个表示a Collection元素的接口,通常将元素添加到一端,然后从另一端删除(FIFO:先进先出)。
  • Stack:表示一个Collection通常在其中从同一端添加(推送)和删除(弹出)元素的位置的接口(LIFO:后进先出)。
  • Deque:“双头队列”的缩写,通常发音为“ deck”。链表通常仅添加到两端(而不是中间)并从中读取。

基本收集图:

图

将元素的插入与ArrayList和进行比较LinkedList

图


2
最好的简短
总结是

11

更简单的图片在这里。故意简化!

  1. 集合是保存称为“元素”(相同类型)的数据的任何东西。没有更具体的假设。

  2. 列表是数据的索引集合,其中每个元素都有一个索引。类似于数组的东西,但更灵活。

    列表中的数据保持插入顺序。

    典型操作:获取第n个元素。

  3. 集合一袋元素,每个元素仅出现一次(元素通过使用equals()方法。

    集中存储数据的目的仅仅是为了知道那里有什么数据。

    典型操作:判断列表中是否存在元素。

  4. Map类似于List,但是您不是通过整数索引访问元素,而是通过 key(任何对象)访问它们。就像PHP中的数组一样:)

    Map中的数据可通过其关键字进行搜索。

    典型的操作:通过其ID(其中ID是任何类型,不仅int是List的情况)来获取元素。

差异

  • 设置并映射:在“设置”中,您可以自己搜索数据,而在“地图”中,可以按其键

  • 列表和地图:在列表中,您可以通过元素的int索引(列表中的位置)访问元素,而在地图中,可以通过其键访问任意类型的元素(通常是ID)

  • 列表和集合:在列表中,元素受其位置限制并且可以重复,而在集合中,元素只是“存在”(pr不存在)并且是唯一的(在equals()或中compareTo()表示SortedSet



1

地图

如果选择a Map,则使该表概括了与Java 11捆绑在一起的十个实现中的每一个的功能。

Java 11中的地图实现表,比较它们的功能



-2

我应该使用哪个Java Collection?

这取决于您要解决的问题或您有什么要求。

例子 :

  1. 您是否希望在存储元素时对它们进行排序?哈希集
  2. 是否要存储(键,值)对?哈希图
  3. 您是否希望保留插入元素的顺序?ArrayList,LinkedList
  4. 您是否要对(Key,Value)对中的键进行排序?- 强文本
  5. 您是否想实现一个堆栈来解决您的问题?- 堆叠
  6. 您是否想要FIFO(先进先出)访问权限?- 排队
  7. 您是否只希望存储UNIQUE元素?--哈希集
  8. 是否要在存储(Key,Value)时允许键为“ Null”?- HashMap中
  9. 您是否想要(Key,Value)对没有NULL值?哈希表

即使将第4项中的强文本替换为例如ConcurrentSkipListMap(K,V),此答案又对Tim B的决策图,对aliteralmind的“短名单说明”有什么影响?
灰胡子

第一点,HashSet不会对数据进行排序,即使不维护插入顺序。您应该使用TreeSet进行更改
Saurabh Mishra,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.