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

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


当前回答

使用哪一种取决于问题本身。我们得看看大O。

图片来源:https://github.com/egonSchiele/grokking_algorithms

其他回答

更新:

正如Mark所指出的那样,在JVM预热之后(几次测试通过)没有明显的差异。检查与重新创建的数组,甚至新传递开始的新行矩阵。有很大的可能性,这表明简单数组的索引访问不用于有利于集合。

前1-2次简单数组还是快2-3倍。

原来的帖子:

对这个主题来说,太多的词太简单了。毫无疑问,数组比任何类容器都快几倍。我在这个问题上为我的性能关键部分寻找替代方案。下面是我为检查实际情况而构建的原型代码:

import java.util.List;
import java.util.Arrays;

public class IterationTest {

    private static final long MAX_ITERATIONS = 1000000000;

    public static void main(String [] args) {

        Integer [] array = {1, 5, 3, 5};
        List<Integer> list = Arrays.asList(array);

        long start = System.currentTimeMillis();
        int test_sum = 0;
        for (int i = 0; i < MAX_ITERATIONS; ++i) {
//            for (int e : array) {
            for (int e : list) {
                test_sum += e;
            }
        }
        long stop = System.currentTimeMillis();

        long ms = (stop - start);
        System.out.println("Time: " + ms);
    }
}

这就是答案:

基于数组(第16行是活动的):

Time: 7064

根据列表(第17行是活动的):

Time: 20950

还有关于“更快”的评论吗?这是可以理解的。问题是什么时候大约3倍的速度比List的灵活性更好。但这是另一个问题。 顺便说一下,我也根据手工构造的数组列表检查了这个。几乎是一样的结果。

如果提前知道数据有多大,那么使用数组会更快。

List更加灵活。你可以使用由数组支持的数组列表。

我同意在大多数情况下,您应该选择数组列表的灵活性和优雅性,而不是数组——在大多数情况下,它对程序性能的影响可以忽略不计。

然而,如果你对软件图形渲染或自定义虚拟机进行很少结构变化(没有添加和删除)的频繁迭代,我的顺序访问基准测试表明,数组列表比我的系统上的数组慢1.5倍(在我一岁的iMac上是Java 1.6)。

一些代码:

import java.util.*;

public class ArrayVsArrayList {
    static public void main( String[] args ) {

        String[] array = new String[300];
        ArrayList<String> list = new ArrayList<String>(300);

        for (int i=0; i<300; ++i) {
            if (Math.random() > 0.5) {
                array[i] = "abc";
            } else {
                array[i] = "xyz";
            }

            list.add( array[i] );
        }

        int iterations = 100000000;
        long start_ms;
        int sum;

        start_ms = System.currentTimeMillis();
        sum = 0;

        for (int i=0; i<iterations; ++i) {
          for (int j=0; j<300; ++j) sum += array[j].length();
        }

        System.out.println( (System.currentTimeMillis() - start_ms) + " ms (array)" );
        // Prints ~13,500 ms on my system

        start_ms = System.currentTimeMillis();
        sum = 0;

        for (int i=0; i<iterations; ++i) {
          for (int j=0; j<300; ++j) sum += list.get(j).length();
        }

        System.out.println( (System.currentTimeMillis() - start_ms) + " ms (ArrayList)" );
        // Prints ~20,800 ms on my system - about 1.5x slower than direct array access
    }
}

虽然建议使用数组列表的答案在大多数情况下是有意义的,但相对性能的实际问题还没有真正得到答案。

你可以用数组做以下几件事:

创建它 设置一个项目 买一件物品 克隆/复制它

一般的结论

虽然get和set操作在数组列表(resp。在我的机器上每次调用1和3纳秒),对于任何非密集的用途,使用ArrayList相对于数组的开销非常小。然而,有几件事要记住:

在列表上调整大小操作(当调用list.add(…)时)代价很高,应该尽可能将初始容量设置为适当的级别(注意,在使用数组时也会出现同样的问题) 在处理原语时,数组可以明显更快,因为它们可以避免许多装箱/拆箱转换 一个只在数组列表中获取/设置值的应用程序(不是很常见!)通过切换到数组可以看到超过25%的性能增益

详细的结果

下面是我在标准x86桌面机器上使用JDK 7使用jmh基准测试库(以纳秒为单位)测量这三个操作的结果。请注意,ArrayList在测试中从不调整大小,以确保结果具有可比性。这里有基准代码。

数组/ ArrayList创造

我运行了4个测试,执行以下语句:

createArray1: Integer[] array = new Integer[1]; createList1: List<Integer> List = new ArrayList<> (1); createArray10000: Integer[] array = new Integer[10000]; createList10000: List<Integer> List = new ArrayList<> (10000);

结果(以纳秒为单位,95%置信度):

a.p.g.a.ArrayVsList.CreateArray1         [10.933, 11.097]
a.p.g.a.ArrayVsList.CreateList1          [10.799, 11.046]
a.p.g.a.ArrayVsList.CreateArray10000    [394.899, 404.034]
a.p.g.a.ArrayVsList.CreateList10000     [396.706, 401.266]

结论:无明显差异。

get操作

我运行了2个测试,执行以下语句:

返回list.get(0); 返回数组[0];

结果(以纳秒为单位,95%置信度):

a.p.g.a.ArrayVsList.getArray   [2.958, 2.984]
a.p.g.a.ArrayVsList.getList    [3.841, 3.874]

结论:从数组中获取信息比从ArrayList中获取信息快25%,尽管差异仅在1纳秒的量级上。

集合操作

我运行了2个测试,执行以下语句:

setList:列表。设置(0,价值); setArray:数组[0]=值;

结果(以纳秒为单位):

a.p.g.a.ArrayVsList.setArray   [4.201, 4.236]
a.p.g.a.ArrayVsList.setList    [6.783, 6.877]

结论:在数组上的set操作比在列表上快40%左右,但是,对于get,每个set操作需要几纳秒——所以为了达到1秒的差异,需要在列表/数组中设置项数亿次!

无性系/ copy

ArrayList的复制构造函数委托给数组。因此,性能与数组复制相同(通过克隆复制数组,数组。copyOf或System。arrayCopy在性能方面没有实质性的差异)。

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

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

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