最近在做图像处理的时候,发现某一段代码非常的慢,慢得让人无法接受。主要的代码是顺序访问一个LinkedList的元素,效果是随着index的变大,速度越来越慢,list的元素个数在百万以上。找到原因,分享出来,也希望大家不要跳入同一个陷阱。还是那一句话,可运行的代码和高质量的代码之间还是有比较远的距离。
代码里面加入了一些打印时间相关的代码,主要是为了直观的显示运行的耗时。
public static void main(String[] args) {
    // add elements
    int size = 2000000;
    List<String> list = new LinkedList<String>();
    for (int i = 0; i < size; i++) {
        list.add("Just some test data");
    }
    long startTime = System.currentTimeMillis();
    for (int i = 0; i < size; i++) {
        list.get(i);
        if (i % 10000 == 0) {
            System.out.println("query 10000 elements spend: "
                    + (System.currentTimeMillis() - startTime));
            startTime = System.currentTimeMillis();
        }
    }
}
控制台输出如下:
错误的代码就是list.get(i),LinkedList的底层是一个链表,随机访问i的时候,链表只能从头往后数,第i个才返回。所以时间随着i的变大时间会越来越长。
顺序访问,LinkedList绝对不要用get方法,即使LinkedList的元素个数只有很少的几个。养成好习惯,免得犯错。
for (String element : list) {
    // process element here
}
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
    String element = iter.next();
    // process element here
}
public static void main(String[] args) {
    // add elements
    int size = 2000000;
    List<String> list = new ArrayList<String>();
    for (int i = 0; i < size; i++) {
        list.add("Just some test data");
    }
    long startTime = System.currentTimeMillis();
    for (int i = 0; i < size; i++) {
        list.get(i);
        if (i % 10000 == 0) {
            System.out.println("query 10000 elements spend: "
                    + (System.currentTimeMillis() - startTime));
            startTime = System.currentTimeMillis();
        }
    }
}
ArrayList的控制台输出如下:
下面比较一下LinkedList和ArrayList的效率。
ArrayList测试代码如下:
public static void main(String[] args) {
    // add elements
    int size = 20000000;
    List<String> list = new ArrayList<String>();
    long startTime = System.currentTimeMillis();
    for (int i = 0; i < size; i++) {
        list.add("Just some test data");
    }
    System.out.println("add " + size + " elements spend: "
            + (System.currentTimeMillis() - startTime));
    // query
    startTime = System.currentTimeMillis();
    String median = list.get(size / 2);
    System.out.println("query median spend: "
            + (System.currentTimeMillis() - startTime));
    // delete
    startTime = System.currentTimeMillis();
    list.remove(median);
    System.out.println("delete median spend: "
            + (System.currentTimeMillis() - startTime));
}
LinkedList测试代码如下:
public static void main(String[] args) {
    // add elements
    int size = 20000000;
    List<String> list = new LinkedList<String>();
    long startTime = System.currentTimeMillis();
    for (int i = 0; i < size; i++) {
        list.add("Just some test data");
    }
    System.out.println("add " + size + " elements spend: "
            + (System.currentTimeMillis() - startTime));
    // query
    startTime = System.currentTimeMillis();
    String median = list.get(size / 2);
    System.out.println("query median spend: "
            + (System.currentTimeMillis() - startTime));
    // delete
    startTime = System.currentTimeMillis();
    list.remove(median);
    System.out.println("delete median spend: "
            + (System.currentTimeMillis() - startTime));
}
尽量使用ArrayList,ArrayList满足不了需求的时候再用LinkedList。根据LinkedList的特点,在下面几种情况下才使用LinkedList。
java.util.List接口之外的APILinkedList的一种错误用法,布布扣,bubuko.com
原文地址:http://blog.csdn.net/kimylrong/article/details/25378785