繁体   English   中英

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

[英]What is the fastest way to store unknown amount of strings in java?

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

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

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

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

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

  • 维持秩序
  • O(1)在头部或尾部添加
  • O(1)在头部或尾部移除
  • 便宜的迭代

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

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

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

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

两个明显的选择是ArrayListLinkedList LinkedList似乎比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机器上。

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

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

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迭代速度也可能非常慢,也可能是因为缺乏局部性。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM