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

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


当前回答

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

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

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

其他回答

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

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

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

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

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

List是java 1.5及以上版本的首选方式,因为它可以使用泛型。数组不能有泛型。数组也有预定义的长度,不能动态增长。初始化一个大数组并不是一个好主意。 ArrayList是用泛型声明数组的方式,它可以动态增长。 但如果删除和插入使用得更频繁,那么链表是使用最快的数据结构。

我不认为这对Strings有什么影响。字符串数组中连续的是对字符串的引用,字符串本身存储在内存中的随机位置。

数组与列表的区别在于基本类型,而不是对象。如果您预先知道元素的数量,并且不需要灵活性,那么由数百万个整数或双精度数组成的数组将比列表在内存和速度上更有效,因为它们确实是连续存储的,并且可以立即访问。这就是为什么Java仍然使用字符数组表示字符串,使用整数数组表示图像数据,等等。

我来这里是为了更好地感受使用列表而不是数组对性能的影响。我不得不为我的场景调整代码:数组/列表的~1000个整型,主要使用getter,即数组[j] vs. list.get(j)

从7个中选择最好的并不科学(前几个列表的速度慢2.5倍),我得到了这样的结果:

array Integer[] best 643ms iterator
ArrayList<Integer> best 1014ms iterator

array Integer[] best 635ms getter
ArrayList<Integer> best 891ms getter (strange though)

用数组大约快30%

现在发表文章的第二个原因是,没有人会提到使用嵌套循环编写数学/矩阵/模拟/优化代码的影响。

假设你有三个嵌套层,而内部循环的速度是原来的两倍,那么你的性能就会下降8倍。一天就能完成的事情现在需要一个星期。

*编辑 这里非常震惊,我试图声明int[1000]而不是Integer[1000]

array int[] best 299ms iterator
array int[] best 296ms getter

使用Integer[] vs. int[]表示双倍的性能打击,带有迭代器的ListArray比int[]慢3倍。真的认为Java的列表实现类似于本机数组…

参考代码(多次调用):

    public static void testArray()
    {
        final long MAX_ITERATIONS = 1000000;
        final int MAX_LENGTH = 1000;

        Random r = new Random();

        //Integer[] array = new Integer[MAX_LENGTH];
        int[] array = new int[MAX_LENGTH];

        List<Integer> list = new ArrayList<Integer>()
        {{
            for (int i = 0; i < MAX_LENGTH; ++i)
            {
                int val = r.nextInt();
                add(val);
                array[i] = val;
            }
        }};

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

        long stop = System.currentTimeMillis();

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