所有
我一直在浏览很多网站,这些网站发布各种各种行动的表现,包括添加元素,搜索和删除。但我也注意到它们都提供了不同的测试环境,即O.S,内存,线程运行等。
我的问题是,是否有任何网站/材料在最佳测试环境基础上提供相同的性能信息?即,配置不应成为任何特定数据结构性能不佳的问题或催化剂。
[Updated]:示例,HashSet和LinkedHashSet都具有插入元素的复杂度O(1)。但是,Bruce Eckel的测试声称,LinkedHashSet的插入时间比HashSet要多[http://www.artima.com/weblogs/viewpost.jsp?thread=122295]。那么我还应该使用Big-Oh表示法吗?
答案 0 :(得分:9)
以下是我的建议:
或者你可以......你知道......不优化。平台和编译器将会改变,但一个好的设计应该 - 平均 - 表现得足够好。
您还可以做的其他事情:
有人说,我不知道为什么你需要提升性能,所以也许你有一个非常有效的理由。
我并不是说选择合适的收藏并不重要。只有那些你知道哪一个选择特定问题,并且你已经看过其他选择,那么你已经完成了你的工作,而不必感到愧疚。这些集合通常具有语义含义,只要你尊重它就可以了。
答案 1 :(得分:6)
在我看来,您需要了解的有关数据结构的所有操作都是对其进行操作的Big-O,而不是来自不同体系结构的主观测量。不同的收藏品有不同的用途。
Map
是字典
Set
断言唯一性
List
提供分组并保留迭代顺序
Tree
提供便宜的排序和快速搜索动态变化的内容,需要不断的排序
已编辑以包含bwawok关于树结构用例的声明
<强>更新强>
来自javadoc on LinkedHashSet
Set接口的哈希表和链表实现,具有可预测的迭代顺序。
...
由于维护链表的额外费用,性能可能略低于HashSet的性能,但有一个例外:对LinkedHashSet的迭代需要与集合大小成比例的时间,而不管其容量如何。对HashSet的迭代可能更昂贵,需要与其容量成比例的时间。
现在我们已经从选择适当的数据结构接口的一般情况转变为使用哪种实现的更具体的情况。但是,我们最终得出的结论是,基于每个实现提供的独特,微妙的不变量,特定实现非常适合特定应用程序。
答案 2 :(得分:5)
您需要了解他们,为什么?基准测试显示给定JDK和硬件设置的原因是它们(理论上)可以再现。你应该从基准测试得到的是对事物如何运作的想法。对于ABSOLUTE数字,您需要根据您自己的代码运行它。
最重要的是要了解各种集合的Big O运行时。知道从未排序的ArrayList中获取元素是O(n),但是从HashMap中获取它是O(1) HUGE 。
如果您已经为给定的工作使用了正确的收藏品,那么您将有90%的收入。当你需要担心从HashMap中获取项目的速度时,应该是非常罕见的。
一旦离开单线程域并进入多线程域,您将需要开始担心ConcurrentHashMap和Collections.synchronized hashmap之类的问题。在你是多线程之前,你可以不用担心这种东西,并专注于哪个集合使用。
更新到HashSet与LinkedHashSet
我还没有找到一个需要链接哈希集的用例(因为如果我关心顺序我倾向于有一个List,如果我关心O(1)获取,我倾向于使用HashSet。实际上,大多数代码都会使用ArrayList,HashMap或HashSet。如果你还需要其他任何东西,你就处于“边缘”状态。
答案 3 :(得分:4)
不同的集合类具有不同的大O表现,但所有这些都告诉你它们随着它们变大而如何扩展。如果你的集合足够大,那么O(1)的集合将胜过具有O(N)或O(logN)的集合,但除了实验之外,没有办法告诉N的什么值是盈亏平衡点。 / p>
一般来说,我只是使用最简单的东西,然后如果它成为一个“瓶颈”,正如该数据结构上的操作占用了大量的时间,那么我将切换到具有更好的大O评级的东西。通常情况下,集合中的项目数量永远不会接近收支平衡点,或者还有另一种简单的方法来解决性能问题。
答案 4 :(得分:1)
HashSet
和LinkedHashSet
都有O(1)表现。与HashMap
和LinkedHashMap
相同(实际上前者是基于后者实现的)。这只会告诉您这些算法 scale 的方式,而不是它们实际执行的方式。在这种情况下,LinkHashSet
执行与HashSet
完全相同的工作,但也始终必须更新上一个和下一个指针以维护订单。这意味着HashSet
的常量(在讨论实际算法性能时这是一个重要值)低于LinkHashSet
。
因此,由于这两个具有相同的Big-O,它们本质上相同 - 即,当 n 发生变化时,两者都具有相同的性能变化并且具有O(1)性能,平均来说,不会改变。
所以现在你的选择是基于功能和你的要求(无论如何,这应该是你首先考虑的)。如果您只需要快速添加和获取操作,则应始终选择HashSet
。如果您还需要一致的排序 - 例如上次访问或插入订单 - 那么必须也使用该类的Linked
...版本。
我在生产应用程序中使用了“链接”类,LinkedHashMap
。我在一个案例中使用了这个符号,如表格,因此需要快速访问符号和相关信息。但我还想按照用户定义这些符号(插入顺序)的顺序在至少一个上下文中输出信息。这使输出对用户更友好,因为他们可以按照定义的顺序查找内容。
答案 5 :(得分:0)
如果我必须排序数百万行,我会尝试找到一种不同的方式。也许我可以改进我的SQL,改进我的算法,或者可能将元素写入磁盘并使用操作系统的sort命令。
我从未遇到过导致我的表现出现问题的收藏品。
答案 6 :(得分:0)
我使用HashSets和LinkedHashSets创建了自己的实验。对于add()和包含运行时间是O(1),没有考虑到很多冲突。在Linkedhashset的add()方法中,我将对象放在用户创建的哈希表中,该表是O(1),然后将对象放在单独的链表中以说明顺序。因此,从linkedhashset中删除元素的运行时间必须在哈希表中找到该元素,然后搜索具有该顺序的链表。因此运行时间分别为O(1)+ O(n),对于remove()
是o(n)