维护插入顺序的Java集合

维护插入顺序的Java集合

问题描述:

为什么某些集合数据结构不能保持插入顺序?与维持插入顺序相比,取得的特殊成就是什么? 如果我们不维护订单,我们会获得一些东西吗?维护插入顺序的Java集合

+1

例如,为什么'java.util.HashSet'需要维护插入顺序? – 2010-09-12 08:09:26

+0

不,我要求..我们在维持秩序时做了什么事情。我们是否会得到一些东西,如果我们不维护订单 – JavaUser 2010-09-12 08:11:28

+0

例如:LinkedList。想想看,将它插入/插入链表比将它插入中间不是更容易吗? – st0le 2010-09-12 09:47:11

表现。如果您想要原始广告订单,则会有LinkedXXX类,它们按广告订单维护额外的链接列表。大部分时间你不关心,所以你使用HashXXX,或者你想要一个自然顺序,所以你使用TreeXXX。在这两种情况下,为什么要支付链表的额外费用?

+7

'ArrayList'在哪里适合答案? – ADTC 2014-09-26 04:42:07

+0

@ADTC它不适合答案。 – EJP 2015-03-20 06:32:48

+0

好吧,ArrayList维护数组后台的插入顺序,但是我认为性能比LinkedXXX类更糟? – ADTC 2015-03-20 12:50:38

取决于你需要什么实施才能做好。插入顺序通常不是很有意思,所以不需要维护它,所以您可以重新排列以获得更好的性能。

对于地图,它通常是使用的HashMap和TreeMap。通过使用散列码,条目可以放在一个小组中,易于搜索.ShitMap以较慢的搜索为代价维护插入条目的排序顺序,但比HashMap更容易排序。

当您使用HashSet(或HashMap)数据存储在基于您的对象的散列的“桶”中。通过这种方式,您的数据更容易访问,因为您无需在整个集合中查找此特定数据,只需查看合适的存储区即可。

这种方式可以提高特定点的表现。

每个集合的实现都有其特殊性,以便在特定条件下使用它更好。这些特点中的每一个都有成本。因此,如果您不需要它(例如插入顺序),则最好使用不提供它的实现,并且更符合您的要求。

我不能引用参考,但通过设计ListSet接口的实现基本上可扩展Array s。由于Collections默认提供了动态的方法添加删除元素在任何点 - 哪一个Array s不 - 可能不会保留插入顺序。 因此,由于有更多的内容处理方法,所以需要特殊的实现来保持顺序。

另一点是性能,因为表现最好的Collection可能不是那个,它保留了它的插入顺序。但我不确定,Collections如何管理其内容以提高性能。

因此,简而言之,我能想到的,为什么有保序Collection实现的两大原因是:

  1. Class架构
  2. 性能
+0

请注意,'Arrays'是一个实际的类,而数组是一种特殊类型的容器对象。我也非常确定LinkedList实际上使用链表,但我没有阅读代码。 :-) – wds 2010-09-12 09:24:03

+0

好吧,点了,我编辑我的帖子。关于你的“LinkedList”评论:我发布的内容与哪个矛盾? – FK82 2010-09-12 09:57:45

+0

澄清:LinkedList afaik是一个List,它的插入顺序保存在另一个List中(其中两个*链接*,因此是名称)。或者,我错了吗? – FK82 2010-09-12 10:04:10

  • 广告订单本质上不保留在hash tables - 这是他们如何工作(阅读链接到的文章,了解细节)。可以添加逻辑来维护插入顺序(如LinkedHashMap),但需要更多的代码,并且在运行时需要更多的内存和更多的时间。性能损失通常不显着,但可以。
  • 对于TreeSet/Map,使用它们的主要原因是接口中添加的自然迭代顺序和其他功能。
+2

+1提及“但需要更多代码”。 – helpermethod 2010-09-12 10:03:16

+1

请注意:严格来说'Map'实现不是'Collection's,因为它们没有实现'Collection'接口。他们确实有类似的方法,但就是这样。检查:http://download.oracle.com/javase/1.4.2/docs/guide/collections/overview.html(#Collection Interfaces)虽然最有可能的OP的问题地址映射。 – FK82 2010-09-12 13:13:00

为什么有必要保持插入顺序?如果您使用HashMap,则可以通过key获取条目。这并不意味着它不提供你想要的类。

集合不保持插入顺序。有些只是默认在最后添加一个新值。维护插入顺序只有在按照对象的优先级排序或以某种方式对对象进行排序时才有用。

至于为什么某些集合默认维护它,其他集合不这样做,这主要是由实现引起的,并且有时只是集合定义的一部分。

  • 列表保持广告订单只是在末处加入一个新的条目或开始是最快实现的add(Object)方法的。

  • 集合 HashSet和TreeSet实现不维护插入顺序,因为对象被快速查找排序并且维护插入顺序需要额外的内存。这会导致性能增益,因为插入顺序对于集合几乎从未感兴趣。

  • ArrayDeque一个deque可以用于简单阙和堆栈,所以你想拥有'先进先出“”或“”后出“的行为,都需要该ArrayDeque保持插入顺序。在这种情况下,插入订单将作为类合同的核心部分进行维护。

+2

非常翔实,特别是关于ArrayDeque。 – Jayy 2013-05-10 11:21:02

即使世界在O'Reilly的Java的食谱一节名为“避免冲动排序”你应该问的问题实际上是你原来的问题相反......“难道我们的排序有所收获? “分类和维护该订单需要花费很多努力。当然,排序很简单,但通常在大多数程序中不能扩展。如果您要每秒处理数千或数万个请求(insrt,del,get等),那么您是否正在使用已排序或未排序的数据结构,这将非常重要。

好吧...所以这些帖子与现在相比是旧的,但是根据您的需要或应用程序要求,需要插入顺序,因此只需使用正确类型的收集。大多数情况下,这不是必需的,但是在需要按照存储顺序使用对象的情况下,我看到了确切的需求。我认为,在创建实例向导或流引擎时,订单很重要,或者需要从一个状态到另一个状态或某事的某种性质。从这个意义上说,你可以读取列表中的东西,而不必跟踪你下一步需要的东西,或者遍历列表来找到你想要的东西。它确实有助于在这个意义上的表现。它确实很重要,否则这些集合没有多大意义。

一些Collection由于没有维护顺序,他们计算内容的hashCode并将其存储在相应的bucket中。