1
338
我建议您使用分析器来测试哪个更快。 我个人认为你应该使用列表。 我在一个大型代码库和以前的开发人员使用的数组组上工作 到处 .这使得代码非常不灵活。在把它的大块更改为列表之后,我们注意到速度上没有差别。 |
2
154
Java方式是你应该考虑什么数据 抽象化 最适合你的需求。请记住,在Java中,列表是抽象的,不是具体的数据类型。您应该将字符串声明为列表,然后使用arraylist实现对其进行初始化。
抽象数据类型和具体实现的分离是面向对象编程的一个关键方面。 ArrayList使用数组作为其基础实现来实现列表抽象数据类型。访问速度实际上与数组相同,它还有另外的优点,即能够向列表中添加和减去元素(尽管这是一个带array list的O(N)操作),如果您决定稍后更改底层实现,则可以。例如,如果您意识到需要同步访问,您可以将实现更改为矢量,而无需重写所有代码。 事实上,arraylist是专门为在大多数上下文中替换低级数组构造而设计的。如果Java现在被设计,那么完全有可能完全忽略数组来支持ARARYLIST结构。
在Java中,所有集合只存储对对象的引用,而不存储对象本身。数组和arraylist都将在一个连续的数组中存储几千个引用,因此它们本质上是相同的。您可以考虑,在现代硬件上,由几千个32位引用组成的连续块总是随时可用的。当然,这并不能保证您不会完全耗尽内存,只是连续的内存块需求对fufil来说并不困难。 |
3
92
您应该更喜欢泛型类型而不是数组。正如其他人所提到的,数组是不灵活的,没有泛型类型的表达能力。(不过,它们确实支持运行时类型检查,但与一般类型的混合很糟糕。) 但是,和往常一样,在优化时,您应该始终遵循以下步骤:
|
4
82
虽然建议使用arraylist的答案在大多数情况下都是有意义的,但是实际的相对性能问题并没有得到真正的回答。 使用数组可以执行以下操作:
一般结论尽管get和set操作在arraylist上稍微慢一些 (RESP)在我的机器上每次呼叫1和3纳秒, 对于任何非密集使用,使用arraylist和数组的开销都很小。 然而,有一些事情需要牢记:
详细结果下面是我使用 jmh benchmarking library (以纳秒为单位)在标准x86台式机上使用JDK7。注意,在测试中,arraylist永远不会调整大小以确保结果具有可比性。 Benchmark code available here . 数组/数组列表创建我运行了4个测试,执行以下语句:
结果(以纳秒为单位,每次调用95%置信度):
结论:无明显差异 . 获取操作我运行了2个测试,执行以下语句:
结果(以纳秒为单位,每次调用95%置信度):
结论:从阵列中获取数据的速度大约快25%。 而不是从阵列列表中获取,尽管差异仅在一纳秒的阶数上。 集合运算我运行了2个测试,执行以下语句:
结果(以纳秒为单位,每次调用):
结论:阵列上的集合运算速度大约快40% 但是,对于get,每个set操作都需要几纳秒的时间-因此,如果差异达到1秒,则需要在列表/数组中设置数亿次的项! 克隆/复制
arraylist的复制构造函数委托给
|
5
22
我猜原来的海报是来自一个C++/STL背景,这造成一些混乱。在C++中
在爪哇
从性能的角度来看,必须通过一个接口和一个额外的对象会有很小的影响,但是运行时内联意味着这几乎没有任何意义。还要记住
如果此特定代码确实对性能敏感,则可以创建一个
|
6
12
我同意在大多数情况下,您应该选择数组列表的灵活性和优雅性,而在大多数情况下,对程序性能的影响是可以忽略的。 但是,如果您在对软件图形渲染或自定义虚拟机进行持续的、繁重的迭代,并且几乎没有结构更改(没有添加和删除),那么我的顺序访问基准测试表明 arraylist比数组慢1.5倍 在我的系统上(Java 1.6在我一岁的iMac上)。 一些代码:
|
7
11
首先,值得澄清的是,在经典的comp-sci数据结构意义上,你的意思是“list”(链表)还是java.util.list?如果您的意思是java.util.list,那么它是一个接口。如果您想使用数组,只需使用arraylist实现,就可以得到类似数组的行为和语义。问题解决了。 如果你是说一个数组和一个链表,这是一个稍有不同的参数,我们回到大O(这里是一个 plain English explanation 如果这是一个不熟悉的术语。 数组;
链表:
所以您可以选择最适合您调整数组大小的方法。如果调整大小、插入和删除很多,那么链接列表可能是更好的选择。如果随机访问很少,情况也是如此。你提到串行访问。如果您主要进行串行访问,修改很少,那么您选择哪一个可能无关紧要。 链表的开销稍高,因为像您所说的,您正在处理可能不连续的内存块和(有效地)指向下一个元素的指针。这可能不是一个重要的因素,除非你正在处理数百万条条目。 |
8
11
我写了一个比较数组和数组的小基准。在我的老式ish笔记本电脑上,遍历5000个元素arraylist的时间是1000次,比等效的数组代码慢10毫秒。 所以,如果你只是在重复列表,而且做了很多,那么 也许吧 值得优化。否则我会使用这个列表,因为当你 做 需要优化代码。
N.B.I
做
注意使用
|
9
6
不,因为从技术上讲,数组只存储对字符串的引用。字符串本身被分配到不同的位置。对于一千个项目,我想说一个列表会更好,更慢,但它提供了更多的灵活性和更容易使用,特别是如果你要调整它们的大小。 |
10
5
如果你有几千个,考虑使用trie。trie是一个类似树的结构,它合并了存储字符串的常见前缀。 例如,如果字符串
Trie将存储:
字符串需要57个字符(包括空终止符,“\0”)用于存储,再加上容纳它们的字符串对象的大小。(事实上,我们应该把所有的大小四舍五入到16的倍数,但是…)大致称之为57+5=62字节。 trie需要29个(包括空终止符“0”)用于存储,再加上trie节点的sizeof,它是对数组的引用和子trie节点的列表。 对于这个例子,结果可能是一样的;对于数千人来说,只要有公共前缀,结果可能就更少了。 现在,当在其他代码中使用trie时,您必须转换为字符串,可能需要使用StringBuffer作为中介。如果许多字符串同时用作字符串,则在trie之外,这是一种损失。 但如果你当时只使用少数——比如说,在字典中查找东西——trie可以为你节省很多空间。绝对比存储在哈希集中的空间小。 你说你是“连续地”访问它们——如果这意味着按字母顺序,那么trie显然也会给你免费的字母顺序,如果你先对它进行深度迭代的话。 |
11
5
更新: 正如Mark所指出的,在JVM预热(几个测试通过)之后,没有显著差异。检查重新创建的数组,甚至从新的矩阵行开始的新过程。很有可能,这个带有索引访问的简单数组符号不会用于集合。 不过,前1-2次通过简单数组的速度还是2-3倍。 原始职位: 太多的文字,主题太简单,无法检查。 无疑问数组比任何类容器快几倍 . 我在这个问题上寻找性能关键部分的替代方案。以下是我为检查实际情况而构建的原型代码:
答案是: 基于数组(第16行处于活动状态):
基于列表(第17行处于活动状态):
对“更快”还有什么评论吗?这是完全可以理解的。问题是什么时候3倍的速度比列表的灵活性更好。但这是另一个问题。
顺便说一句,我也检查了这个人工构造的
|
12
5
由于这里已经有很多好的答案,我想给你一些其他的实际观点的信息,也就是 插入和迭代性能比较:Java中的原始数组与链表。
这是实际的简单性能检查。
用于此操作的源代码如下:
性能结果如下:
|
13
4
请记住,AARYLIST封装了一个数组,因此与使用原始数组相比,几乎没有什么区别(除了在Java中更容易使用列表)。 与ArrayList相比,选择数组几乎唯一合理的时间是存储基元(如byte、int等),并且需要使用基元数组获得的特定空间效率。 |
14
4
在存储字符串对象的情况下,数组与列表的选择并不那么重要(考虑性能)。因为数组和列表都将存储字符串对象引用,而不是实际对象。
|
15
3
如果您事先知道数据有多大,那么数组将更快。 列表更灵活。可以使用由数组支持的ArrayList。 |
16
3
列表比数组慢。如果需要效率,请使用数组。如果需要灵活性,请使用列表。 |
17
3
如果你能以一个固定的大小生活,阵列将更快,需要更少的内存。 如果您需要添加和删除元素的列表接口的灵活性,那么问题仍然是您应该选择哪个实现。通常,在任何情况下都建议使用arraylist,但如果必须删除或插入列表开头或中间的元素,则arraylist也有其性能问题。 所以你可能想看看 http://java.dzone.com/articles/gaplist-%E2%80%93-lightning-fast-list 介绍了GAPLIST。这个新的列表实现结合了arraylist和linkedlist的优点,几乎对所有操作都有很好的性能。 |
18
2
取决于实现。一个基元类型的数组可能比arraylist更小,效率更高。这是因为数组将直接将值存储在连续的内存块中,而最简单的ArrayList实现将存储指向每个值的指针。尤其是在64位平台上,这会产生巨大的差异。 当然,对于这种情况,JVM实现可能有一个特殊的情况,在这种情况下,性能将是相同的。 |
19
2
清单是Java 1.5及其后的首选方法,因为它可以使用泛型。数组不能有泛型。数组也有一个预先定义的长度,不能动态增长。初始化较大的数组不是一个好主意。 ArrayList是用泛型声明数组的方法,它可以动态增长。 但是,如果更频繁地使用删除和插入,那么链表就是要使用的最快的数据结构。 |
20
2
建议在任何地方使用数组,您可以使用它们而不是列表,特别是在您知道项计数和大小不会改变的情况下。 参见Oracle Java最佳实践: http://docs.oracle.com/cd/A97688_16/generic.903/bp/java.htm#1007056 当然,如果您需要多次从集合中添加和删除对象,那么使用简单的列表。 |
21
2
这个图表显示了Java 7上的n=5的基准。但是,图片不会随着更多的项目或其他虚拟机发生太大的变化。CPU开销可能看起来不太大,但会增加。很可能数组的使用者必须将其转换为集合才能对其执行任何操作,然后将结果转换回数组以将其馈送到另一个接口方法等。
使用简单
此操作在恒定时间内执行,因此它比上述任何操作(黄色条)快得多。这与防御拷贝不同。不可修改的集合将在内部数据更改时更改。如果发生这种情况,客户端可能会遇到
|
22
2
没有一个答案有我感兴趣的信息——对同一个数组进行多次重复扫描。必须为此创建JMH测试。 结果 (Java1.80yxx32,迭代普通数组至少比ARARYLIST快5倍):
试验
|
23
2
“千”不是一个大数字。几千个段落长度的字符串的大小是几兆字节。如果您只想连续访问这些文件,请使用 an immutable singly-linked List . |
24
1
没有适当的基准,不要陷入优化的陷阱。正如其他人所建议的,在做出任何假设之前使用一个分析器。 您枚举的不同数据结构具有不同的用途。列表在开始和结束时插入元素非常有效,但是在访问随机元素时会遇到很多问题。阵列具有固定的存储空间,但提供快速的随机访问。最后,ArrayList通过允许数组增长来改进数组的接口。通常,要使用的数据结构应该由如何访问或添加存储的数据来决定。 关于内存消耗。你好像把一些东西混在一起了。数组只会为您所拥有的数据类型提供一个连续的内存块。不要忘记Java有固定的数据类型:布尔、char、int、长、浮点和对象(包括所有对象,甚至数组都是对象)。这意味着,如果声明一个字符串数组[1000]或MyObject MyObjects[1000],则只能获得1000个足够大的内存框来存储对象的位置(引用或指针)。你得不到1000个足够大的内存箱来容纳对象的大小。别忘了,您的对象首先是用“new”创建的。这是在内存分配完成之后,在数组中存储一个引用(它们的内存地址)。对象不会被复制到数组中,只会被它引用。 |
25
1
我认为这对弦乐没有真正意义。字符串数组中连续的是对字符串的引用,字符串本身存储在内存中的随机位置。 数组和列表可以对基元类型产生影响,而不是对对象。 如果 您预先知道元素的数量,不需要灵活性,一个由数百万个整数或双精度数组成的数组在内存中效率更高,速度略高于列表,因为实际上它们将被连续存储并立即访问。这就是为什么Java仍然使用字符串的字符数组,图像数据的数组,等等。 |
26
1
阵列更快-所有内存都是预先分配的。 |
27
1
这里给出的许多微基准发现了一些纳秒数,比如数组/数组列表读取。如果一切都在一级缓存中,这是非常合理的。 更高级别的缓存或主内存访问的数量级可以是10ns-100ns,而一级缓存的数量级可以是1ns。访问一个arraylist有一个额外的内存间接寻址,在一个真正的应用程序中,您可以根据访问之间的代码所做的,从几乎从不到每次都为此付出任何代价。当然,如果你有很多小的数组列表,这可能会增加你的内存使用,使它更有可能出现缓存未命中。 原来的海报似乎只用了一张,而且在短时间内访问了大量内容,所以应该不会有太大的困难。但对其他人来说可能是不同的,在解释微基准时你应该小心。 然而,Java字符串是非常浪费的,特别是如果你存储了很多小的字符串(用内存分析器查看它们,对于几个字符的字符串来说,它似乎是60字节)。字符串数组与string对象有间接关系,另一个从string对象指向包含字符串本身的char[]。如果有什么东西会破坏你的一级缓存,就是这个,加上数千或数万个字符串。所以,如果你是认真的-真正认真的-关于尽可能多的刮掉性能,那么你可以考虑用不同的方式来做。例如,您可以持有两个数组,一个char[]中包含所有字符串,一个接一个,以及一个int[]中包含开始的偏移量。这将是一个皮塔做任何事情,你几乎肯定不需要它。如果你选择了,你就选错了语言。 |
28
1
我来这里是为了更好地了解在数组上使用列表对性能的影响。我必须在这里为我的场景调整代码:数组/列表大约1000个int,主要使用getter,这意味着数组[j]与list.get(j) 从7个最好的例子来看,这是不科学的(前几个列表中慢了2.5倍),我得到了:
-所以,阵列的速度大约快30% 现在发布的第二个原因是,如果使用数学/矩阵/模拟/优化代码 嵌套的 循环。 假设您有三个嵌套的级别,并且内部循环的速度是性能命中率的8倍。一天之内就可以运行的东西现在需要一周时间。 *编辑 我在这里非常震惊,因为我试图声明int[1000]而不是integer[1000]
使用integer[]与int[]表示双重性能命中,使用迭代器的listarray比int[]慢3倍。真的认为Java的列表实现类似于本机数组… 参考代码(多次调用):
|
29
0
这取决于您必须如何访问它。 在存储之后,如果您主要想执行搜索操作,只需很少或没有插入/删除,那么可以使用数组(在数组的O(1)中进行搜索,而添加/删除可能需要重新排序元素)。 在存储之后,如果您的主要目的是添加/删除字符串,而搜索操作很少或没有,那么请转到列表。 |
30
0
数组比数组快 因为arraylist在内部使用array。如果我们可以直接在数组中添加元素,间接在数组中添加元素 数组通过arraylist总是直接机制比间接机制快。
arraylist类中有两个重载的add()方法:
数组列表的大小是如何动态增长的?
从上面的代码中需要注意的一点是,在添加元素之前,我们正在检查arraylist的容量。ensureCapacity()确定被占用元素的当前大小以及数组的最大大小。如果填充元素(包括要添加到ArrayList类的新元素)的大小大于数组的最大大小,则增大数组的大小。但是数组的大小不能动态增加。因此,内部所发生的是,新的阵列是用容量创建的 到Java 6为止
(更新)从Java 7
另外,来自旧数组的数据将被复制到新数组中。
在arraylist中有开销方法,这就是为什么array比
|
danial · 如何在多个字符串的每个位置找到最频繁的字符 2 年前 |
shekharsabale · 从列表元素捕获子字符串 2 年前 |
The Great · 拆分并存储数据帧,但名称基于特定列中的唯一值 2 年前 |
Klimt865 · Python中的列表列表 2 年前 |
Klimt865 · 在Python中将数组列表转换为列表列表 2 年前 |