Java - 哪种集合在性能方面最适合这种情况?

时间:2014-07-17 12:34:19

标签: java performance collections arraylist set

我正在编写一个需要从文件中读取字符串并将它们存储在某个数据结构中的类。鉴于以下情况,我应该使用什么:

  • 该文件最多包含数百个字符串(它们需要存储在一个结构中,不能流式传输)。
  • 条目需要按特定顺序存储。
  • 一旦排序,集合将不会被修改(它不必是不可变的,但我知道它不会被修改)。
  • 我需要多次遍历该集合。
  • 如果集合中有重复的条目,则只应存储其中一个。

以下answer(和其他人)说如果我只需要排序一次,因为它读取速度更快,那么ArrayList会更好,但如果我使用ArrayList,那么我必须确保它们是手动唯一的。

5 个答案:

答案 0 :(得分:2)

您可以使用TreeSet。它是一个集合,因此它不会存储重复的条目。它在插入时直接对条目进行排序。基本操作需要log(n)时间。因此,总体时间要求类似于先插入列表然后使用n*log(n)排序算法。

答案 1 :(得分:1)

如果您可以在插入时对元素进行排序,请考虑使用TreeSet(如果需要,可以使用自定义的Comparator)。 如果没有,似乎你可能需要两种结构:

  1. 用于初始填充和排序的ArrayList。
  2. 之后,一个LinkedHashSet,以确保奇点,同时保留秩序。

答案 2 :(得分:1)

您可能想要使用LinkedHashSet,即:

Hash table and linked list implementation of the Set interface, with predictable iteration order

...

This implementation spares its clients from the unspecified, generally chaotic ordering provided by HashSet, without incurring the increased cost associated with TreeSet.

答案 3 :(得分:1)

我做了一点TreeSet与ArrayList插入/性能的基准测试。显然ArrayList执行得更好,但是,有一百万个唯一记录,279ms的完整迭代时间并不是那么糟糕。

如果在你的情况下时间可以忽略不计,我会坚持使用TreeSet。否则,在将元素插入ArrayList之前,您将被迫重新使用方向盘并手动检查重复项。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeSet;

public class TestTreeSetVsArrayList {
    public static int ENTRIES = 10000000;

    public static void main(String[] args) {
        TreeSet<String> treeSet = new TreeSet<String>();
        ArrayList<String> arrayList = new ArrayList<String>(10000);
        long l = System.currentTimeMillis();
        for (int i = 0; i < TestTreeSetVsArrayList.ENTRIES; i++) {
            treeSet.add("String"+i);
        }
        System.out.println("treeset insertion time: "+ (System.currentTimeMillis()-l));
        l = System.currentTimeMillis();
        for (int i = 0; i < TestTreeSetVsArrayList.ENTRIES; i++) {
            treeSet.add("String"+i);
        }
        System.out.println("arraylist insertion time: "+ (System.currentTimeMillis()-l));

        Iterator<String> iter;
        iter = treeSet.iterator();
        l = System.currentTimeMillis();
        while(iter.hasNext()) {
            iter.next();
        }
        System.out.println("treeset iteration time: "+ (System.currentTimeMillis()-l));

        iter = arrayList.iterator();
        l = System.currentTimeMillis();
        while(iter.hasNext()) {
            iter.next();
        }
        System.out.println("arraylist iteration time: "+ (System.currentTimeMillis()-l));

    }

}

我的电脑上的结果是:

  

treeset插入时间:11350

     

arraylist插入时间:3583

     

treeset迭代时间:279

     

arraylist迭代时间:0

答案 4 :(得分:0)

如果您可以随时排序:将字符串插入Set(最好HashSet,我推测),然后将它们溢出到ArrayList并排序。