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

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


当前回答

这取决于实现。基元类型数组可能比ArrayList更小更高效。这是因为数组将直接将值存储在一个连续的内存块中,而最简单的ArrayList实现将存储指向每个值的指针。特别是在64位平台上,这可能会产生巨大的差异。

当然,对于这种情况,jvm实现有可能有一个特殊情况,在这种情况下,性能将是相同的。

其他回答

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.

我写了一个比较数组列表和数组的基准测试。在我的老式笔记本电脑上,遍历5000个元素的数组列表1000次的时间比等效的数组代码慢了大约10毫秒。

所以,如果你什么都不做,只是迭代列表,而且你做了很多,那么也许它值得优化。否则,我会使用列表,因为当你需要优化代码时,它会让你更容易。

注意:我确实注意到,使用for String s: stringsList比使用老式的for循环访问列表要慢50%左右。去图…这是我计时的两个函数;数组和列表由5000个随机(不同的)字符串填充。

private static void readArray(String[] strings) {
    long totalchars = 0;
    for (int j = 0; j < ITERATIONS; j++) {
        totalchars = 0;
        for (int i = 0; i < strings.length; i++) {
            totalchars += strings[i].length();

        }
    }
}

private static void readArrayList(List<String> stringsList) {
    long totalchars = 0;
    for (int j = 0; j < ITERATIONS; j++) {
        totalchars = 0;
        for (int i = 0; i < stringsList.size(); i++) {
            totalchars += stringsList.get(i).length();
        }
    }
}

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

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

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

首先,有必要澄清一下,您是指经典的compp sci数据结构意义上的“列表”(即链表),还是指java.util.List?如果你指的是java.util。List,它是一个接口。如果你想使用数组,只要使用数组列表实现,你就会得到类似数组的行为和语义。问题解决了。

如果你指的是数组和链表,这是一个稍微不同的参数,我们回到大O(如果这是一个不熟悉的术语,这里有一个简单的英语解释。

数组;

随机存取:O(1); 插入:O (n); 删除:O (n)。

链表:

随机存取:O(n); 插入:O (1); 删除:O(1)。

你可以选择最适合调整数组大小的方法。如果你调整大小,插入和删除很多,那么链表可能是一个更好的选择。如果随机访问很少,情况也是如此。你提到了串行访问。如果你主要做串行访问,很少修改,那么你选择哪一个可能都不重要。

链表的开销略高,因为正如您所说,您正在处理潜在的不连续内存块和(有效地)指向下一个元素的指针。但是,除非您要处理数百万个条目,否则这可能不是一个重要因素。

这取决于实现。基元类型数组可能比ArrayList更小更高效。这是因为数组将直接将值存储在一个连续的内存块中,而最简单的ArrayList实现将存储指向每个值的指针。特别是在64位平台上,这可能会产生巨大的差异。

当然,对于这种情况,jvm实现有可能有一个特殊情况,在这种情况下,性能将是相同的。