在java中存储未知数量的字符串的最快方法是什么?

时间:2012-02-26 18:47:29

标签: java list collections

我想存储未知数量的字符串,然后按照添加顺序读取它们。正如我所说,我需要的唯一功能是:

  • 可以添加未知数量的字符串而不会因为调整大小而减慢速度
  • 按照添加顺序阅读元素的可能性

问题是我想从trie的一部分输出字符串。因此,在返回字符串之前计算字符串会使操作所需的时间加倍。

(另一个解决方案是使用属性跟踪trie中的字符串数量,但因为我想只返回trie的一部分,这也不是一个完美的解决方案)

4 个答案:

答案 0 :(得分:7)

LinkedList<string>对我来说听起来不错......

  • 维护订单
  • O(1)头部或尾部添加
  • 头部或尾部的O(1)移除
  • 廉价迭代

获取任意元素是很昂贵的,这是不使用它的正常原因......但听起来这在你的情况下不是问题。

答案 1 :(得分:3)

ArrayList通常比LinkedList快。如果没有指定合适的大小,则每次容量耗尽时,都必须重新分配一个新数组(使用double大小),然后将元素复制到新数组中。

您可以使用LinkedList来避免此费用,但平均时间可能会更长。

无论您使用什么样的集合,如果您没有足够的内存,GC将会触发,这也可能会引入一些延迟。没有任何限制的“未知数量”不可能存储在任何内存中的集合中。如果“unknown”可能非常大并且禁止使用内存中的集合,那么您将需要我们一个文件或数据库。

答案 2 :(得分:2)

两个显而易见的选择是ArrayListLinkedListLinkedList似乎比ArrayList略慢。这是我的基准代码:

import java.util.*;

public class ListTest {
    private static final int N = 50000;
    private static final float NANO_TO_MILLI = 1.0e-6f;

    public static void main(String[] args) {
        String[] strings = new String[N];
        for (int i = 0; i < N; ++i) {
            strings[i] = Integer.toString(i);
        }

        System.out.print("ArrayList: ");
        benchmark(strings, new ArrayList<String>());

        System.out.print("LinkedList: ");
        benchmark(strings, new LinkedList<String>());
    }

    private static void benchmark(String[] strings, List<String> list) {
        // measure how long it takes to add the strings
        long start = System.nanoTime();
        for (String s : strings) {
            list.add(s);
        }
        long addTime = System.nanoTime() - start;

        // measure how long it takes to iterate the list
        start = System.nanoTime();
        int i = 0;
        for (String s : list) {
            ++i;
        }
        long iterateTime = System.nanoTime() - start;

        // report the results
        System.out.println(String.format("add: %.2fms; iterate: %.2fms (%d strings)",
            addTime * NANO_TO_MILLI,
            iterateTime * NANO_TO_MILLI,
            i));
    }
}

以下是典型运行的结果:

  

ArrayList:add:5.52ms;迭代:7.66ms(50000弦)
  LinkedList:add:7.79ms;迭代:8.32ms(50000个字符串)

这是在配备Intel Core2 Quad Q6600 2.4GHz cpu的Windows机器上。

请注意,这仅衡量总时间。它不会测量单个字符串的添加时间的变化,由于需要重新分配内部数组,因此我认为ArrayList的字符串比LinkedList更高。

编辑:如果我修改main连续五次重复测试,并在每次调用System.gc()后调用benchmark,那么我会得到一些有趣的结果:< / p>

  

ArrayList:add:5.84ms;迭代:7.84ms(50000弦)
  LinkedList:add:7.24ms;迭代:8.27ms(50000个字符串)

     

ArrayList:add:0.45ms;迭代:0.60ms(50000弦)
  LinkedList:add:0.84ms;迭代:5.35ms(50000个字符串)

     

ArrayList:add:0.52ms;迭代:0.72ms(50000弦)
  LinkedList:add:0.81ms;迭代:5.57ms(50000字符串)

     

ArrayList:add:3.77ms;迭代:0.71ms(50000弦)
  LinkedList:add:3.35ms;迭代:0.93ms(50000字符串)

     

ArrayList:add:3.39ms;迭代:0.87ms(50000弦)
  LinkedList:add:3.38ms;迭代:0.86ms(50000个字符串)

这可能是由于cpu的缓存造成的。请注意,LinkedList可以稍微加快(例如,最后一次迭代)添加字符串,尽管它也可能慢得多。 LinkedList的迭代速度也可能明显变慢,也可能是因为缺乏局部性。

答案 3 :(得分:1)

使用List接口的实现。它是generally consideredArrayList是最好的通用集合,所以要做一些简单的事情来存储你的字符串:

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