我必须在内存中保留数千个字符串,以便在Java中串行访问。我应该把它们存储在数组中还是应该使用某种列表?

由于数组将所有数据保存在一个连续的内存块中(与list不同),使用数组存储数千个字符串会导致问题吗?


当前回答

在存储字符串对象的情况下,数组还是列表的选择并不那么重要(考虑到性能)。因为数组和列表存储的都是字符串对象引用,而不是实际对象。

如果字符串的数量几乎是常数,则使用数组(或ArrayList)。但如果数字变化太大,那么你最好使用LinkedList。 如果有(或将会)需要在中间添加或删除元素,那么你当然必须使用LinkedList。

其他回答

A List更灵活....所以List比array更好

Java的方式是,您应该考虑哪种数据抽象最适合您的需求。记住,在Java中,List是抽象的数据类型,而不是具体的数据类型。您应该将字符串声明为List,然后使用ArrayList实现初始化它。

List<String> strings = new ArrayList<String>();

抽象数据类型和特定实现的分离是面向对象编程的一个关键方面。

An ArrayList implements the List Abstract Data Type using an array as its underlying implementation. Access speed is virtually identical to an array, with the additional advantages of being able to add and subtract elements to a List (although this is an O(n) operation with an ArrayList) and that if you decide to change the underlying implementation later on you can. For example, if you realize you need synchronized access, you can change the implementation to a Vector without rewriting all your code.

事实上,ArrayList是专门为在大多数情况下替换低级数组构造而设计的。如果Java是今天设计的,那么完全有可能将数组完全排除在外,转而使用数组列表结构。

由于数组将所有数据保存在一个连续的内存块中(与list不同),使用数组存储数千个字符串会导致问题吗?

In Java, all collections store only references to objects, not the objects themselves. Both arrays and ArrayList will store a few thousand references in a contiguous array, so they are essentially identical. You can consider that a contiguous block of a few thousand 32-bit references will always be readily available on modern hardware. This does not guarantee that you will not run out of memory altogether, of course, just that the contiguous block of memory requirement is not difficult to fufil.

我建议您使用分析器来测试哪个更快。

我个人的观点是你应该使用列表。

我在一个大型代码库中工作,之前的一组开发人员在任何地方都使用数组。这使得代码非常不灵活。在将大块数据转换为列表后,我们发现速度没有变化。

如果你有几千个,考虑使用trie。trie是一种树状结构,它合并了存储字符串的公共前缀。

例如,如果字符串是

intern
international
internationalize
internet
internets

该树将存储:

intern
 -> \0
 international
 -> \0
 -> ize\0
 net
 ->\0
 ->s\0

字符串需要57个字符(包括空结束符'\0')来存储,再加上存储它们的String对象的大小。(事实上,我们可能应该四舍五入到16的倍数,但是……)粗略地称它为57 + 5 = 62字节。

这个trie需要29个存储空间(包括空结束符'\0'),加上对trie节点的sizeof,这些节点是一个数组的引用和一列子trie节点。

在这个例子中,结果可能是一样的;对于成千上万的人来说,只要你有共同的前缀,它可能会更少。

现在,在其他代码中使用trie时,必须转换为String,可能使用StringBuffer作为中介。如果在trie之外,同时使用了许多字符串作为字符串,这是一种损失。

但如果你一次只使用几个——比如,在字典中查找东西——trie可以为你节省很多空间。绝对比存储在HashSet中的空间要小。

你说你是“连续地”访问它们——如果这意味着按字母顺序访问,如果你深度优先迭代,trie显然也会免费给你字母顺序。

数组-当我们必须实现更快的结果获取时,它总是更好的

列表——执行插入和删除的结果,因为它们可以在O(1)中完成,这也提供了方便地添加、获取和删除数据的方法。更容易使用。

但是始终记住,当数据存储在数组中的索引位置是已知的时,数据的抓取将是快速的。

这可以通过对数组排序很好地实现。因此,这增加了获取数据的时间(即;存储数据+排序数据+寻找数据所在的位置)。因此,这增加了从数组中获取数据的额外延迟,即使它们可能擅长更快地获取数据。

因此,这可以用三元数据结构或三元数据结构来解决。如上所述,树数据结构在搜索数据时非常有效,对特定单词的搜索可以在O(1)量级上完成。当时间紧迫时;如果你必须快速搜索和检索数据,你可以使用三种数据结构。

如果你希望你的内存空间消耗更少,你希望有一个更好的性能,那么使用三元数据结构。这两个都适合存储大量的字符串(例如;比如字典里的单词)。