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

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


当前回答

如果你有几千个,考虑使用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显然也会免费给你字母顺序。

其他回答

如果你可以使用固定的大小,数组将会更快,需要更少的内存。

如果您需要List接口在添加和删除元素方面的灵活性,那么问题仍然是应该选择哪种实现。通常在任何情况下都推荐使用ArrayList,但如果必须删除或插入列表开头或中间的元素,ArrayList也有其性能问题。

因此,您可能想要看看https://dzone.com/articles/gaplist-lightning-fast-list,它介绍了GapList。这个新的列表实现结合了ArrayList和LinkedList的优点,使得几乎所有的操作都有很好的性能。请登录https://github.com/magicwerk/brownies-collections获取。

列表比数组慢。如果需要效率,请使用数组。如果你需要灵活性,使用列表。

数组更快-所有内存都是预先分配的。

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

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

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

不要在没有适当基准测试的情况下陷入优化的陷阱。正如其他人建议的那样,在做出任何假设之前使用分析器。

您所列举的不同数据结构具有不同的用途。列表在开头和结尾插入元素时非常有效,但在访问随机元素时却很困难。数组具有固定的存储,但提供快速的随机访问。最后,ArrayList通过允许数组增长来改进与数组的接口。通常,要使用的数据结构应该由如何访问或添加存储的数据来决定。

About memory consumption. You seem to be mixing some things. An array will only give you a continuous chunk of memory for the type of data that you have. Don't forget that java has a fixed data types: boolean, char, int, long, float and Object (this include all objects, even an array is an Object). It means that if you declare an array of String strings [1000] or MyObject myObjects [1000] you only get a 1000 memory boxes big enough to store the location (references or pointers) of the objects. You don't get a 1000 memory boxes big enough to fit the size of the objects. Don't forget that your objects are first created with "new". This is when the memory allocation is done and later a reference (their memory address) is stored in the array. The object doesn't get copied into the array only it's reference.