ArrayList与LinkedList效率对比

ArrayList与LinkedList效率对比

概述

  1. ArrayList 是一个动态数组,它是线程不安全的,允许元素为null。其底层数据结构依然是数组,因为实现了RandomAccess接口,所以拥有随机快速访问的能力,ArrayList可以以O(1)的时间复杂度去根据下标访问元素。由于数组的内存连续,可以根据下标以O1的时间改查元素,因此时间效率很高
  2. LinkedList 是一个双向链表,它是 线程不安全的,允许元素为null。其底层数据结构是链表,和ArrayList比,没有实现RandomAccess接口,所以其以下标,随机访问元素速度较慢。但它的增删只需要移动指针即可,故时间效率较高

总体而言,ArrayList的改查效率高,LinkedList的增删效率高,真实情况下是否如此呢?

ArrayList 、LinkedList效率对比

1.插入

    /**
     * 顺序插
     */
    @Test
    public void test() {
        ArrayList<String> arr = new ArrayList<>();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 200000; i++) {
            arr.add("a");
        }
        long end = System.currentTimeMillis();
        System.out.println("arrylist time:" + (end - start));

        LinkedList<String> link = new LinkedList<>();
        start = System.currentTimeMillis();
        for (int i = 0; i < 200000; i++) {
            link.addLast("a");
        }
        end = System.currentTimeMillis();
        System.out.println("linkedlist time:" + (end - start));

    }

可以发现,结果与我们预计的相同。LinkedList插入速度快于ArrayList。

但是,我们将插入的数值加大到100w。

ArrayList的插入速度居然快于LinkedList,这是为什么呢?

因为ArrayList每次需要扩容的话,新数组是旧数组容量的1.5倍,再使用Arrays.copyOf()将旧数组中的元素复制到新数组,不需要扩容的话则直接插入。插入数据的大部分时间用来复制数组。

而LinkedList每次添加元素需要构建节点,再将新节点插入队尾。插入数据的大部分时间用来构建节点。

当元素很少的时候,构建节点所需的时间少于数组复制的时间,但是当元素急剧增多的时候,ArrayList数组扩容到足够大,已经足够添加所有元素,此时不需要再次扩容,所以几乎没有复制数组的时间。而LinkedList链表添加时间随着元素的不断增多而增多。

让我们再测试各个位置添加元素的效率

/**
 * 头插入 array < linked
 */
@Test
public void test1() {
    ArrayList<String> arr = new ArrayList<>();
    long start = System.currentTimeMillis();
    for (int i = 0; i < 200000; i++) {
        arr.add(0, "a");
    }
    long end = System.currentTimeMillis();
    System.out.println("arrylist time:" + (end - start));

    LinkedList<String> link = new LinkedList<>();
    start = System.currentTimeMillis();
    for (int i = 0; i < 200000; i++) {
        link.add(0, "a");
    }
    end = System.currentTimeMillis();
    System.out.println("linkedlist time:" + (end - start));

}

这是因为ArrayList每次插入新元素都要将后面所有元素向后移动一位,这是ArrayList插入最坏的情况。

    /**
     * 中间插 1.数据量低于150w LinkedList 》 ArrayList
     *        2.数据量大于150w ArrayList 《 LinkedList
     */
    @Test
    public void test3() {
        ArrayList<String> arr = new ArrayList<>();
        for (int i = 0; i < 1500000; i++) {
            arr.add("a");
        }
        long start = System.currentTimeMillis();

        for (int i = 0; i < arr.size() / 2; i++) {
            arr.add("a");
        }
        long end = System.currentTimeMillis();
        System.out.println("arrylist time:" + (end - start));

        LinkedList<String> link = new LinkedList<>();
        for (int i = 0; i < 1500000; i++) {
            link.add("a");
        }
        start = System.currentTimeMillis();
        for (int i = 0; i < link.size() / 2; i++) {
            link.add("a");
        }
        end = System.currentTimeMillis();
        System.out.println("linkedlist time:" + (end - start));

    }

当插入的数据量是140w时

LinkedList小胜ArrayList一筹。但当数据量增加到150w时

LinkedList的插入所需时间急剧增多,而ArrayList所需时间基本保持不变,可以认为150w是两者的转折点。

LinkedList在指定位置插入需要先移动移动指针到指定位置,虽然将链表分成前后两部分进行查找,但是速度明显慢于数组,这在随机插入中表现更加明显。

/**
 * 随机插入 array >> linked
 */
@Test
public void test4() {
    List<String> list = new ArrayList<>();
    Random random = new Random();
    long start = System.currentTimeMillis();
    for (int i = 1; i < 50000; i++) {
        int x = random.nextInt(i);
        list.add(x, "a");
    }
    long end = System.currentTimeMillis();
    System.out.println("arrayList insert time " + (end - start));

    List<String> list1 = new LinkedList<>();
    start = System.currentTimeMillis();
    for (int i = 1; i < 50000; i++) {
        int x = random.nextInt(i);
        list1.add(x, "a");
    }
    end = System.currentTimeMillis();
    System.out.println("linkedList insert time " + (end - start));
}

只是插入5w数据,差距已经如此明显。

综上所述,除了经常进行头插入的情况,一般情况下插入优先考虑使用ArrayList。

2.读取

ArrayList拥有快速访问能力,不管是随机读还是顺序读,效率都高于LinkedList。

/**
 * 随机读 array > linked
 */
@Test
public void test6() {
    List<String> arr = new ArrayList<>();
    Random random = new Random();
    for (int i = 0; i < 200000; i++) {
        arr.add("a");
    }
    List<String> linked = new LinkedList<>();
    for (int i = 0; i < 200000; i++) {
        linked.add("a");
    }
    long start = System.currentTimeMillis();
    for (int i = 1; i < arr.size(); i++) {
        int x = random.nextInt(i);
        arr.get(x);
    }
    long end = System.currentTimeMillis();
    System.out.println("arrayList insert time " + (end - start));

    start = System.currentTimeMillis();
    for (int i = 1; i < linked.size(); i++) {
        int x = random.nextInt(i);
        linked.get(i);
    }
    end = System.currentTimeMillis();
    System.out.println("linkedList insert time " + (end - start));
}
/**
 * 顺序删 array 》 linked
 */
@Test
public void test7() {
    ArrayList<String> arr = new ArrayList<>();
    for (int i = 0; i < 20000; i++) {
        arr.add("a");
    }
    long start = System.currentTimeMillis();
    for (int i = 0; i < arr.size(); i++) {
        arr.remove(i);
    }
    long end = System.currentTimeMillis();
    System.out.println("arrylist time:" + (end - start));

    LinkedList<String> link = new LinkedList<>();
    for (int i = 0; i < 20000; i++) {
        link.add("a");
    }
    start = System.currentTimeMillis();
    for (int i = 0; i < link.size(); i++) {
        link.remove(i);
    }
    end = System.currentTimeMillis();
    System.out.println("linkedlist time:" + (end - start));
}

3.删除与插入同理,不管是随机删还是顺序删,ArrayList 的效率都要高于LinkedList。

原文地址:https://www.cnblogs.com/le-le/p/12347303.html

时间: 2024-10-08 03:51:17

ArrayList与LinkedList效率对比的相关文章

比较ArrayList、LinkedList、Vector

翻译人员: 铁锚 翻译时间: 2013年12月2日 原文链接: ArrayList vs. LinkedList vs. Vector 1. List概述 List,就如图名字所示一样,是元素的有序列表.当我们讨论List时,将其与Set作对比是一个很好的办法,Set集合中的元素是无序且唯一的. 下图是Collection的类继承图,从图中你可以对本文所讨论的知识有大致的了解. 图1 2. ArrayList.LinkedList与Vector的对比 从图中可以看出,这三者都实现了List 接口

【Simple Java】ArrayList vs LinkedList vs Vector

List概览 List,正如它的名字,表明其是有顺序的.当讨论List的时候,最好拿它跟Set作比较,Set中的元素是无序且唯一:下面是一张类层次结构图,从这张图中,我们可以大致了解java集合类的整体架构: ArrayList vs LinkedList vs Vector 从上面的类层次结构图中,我们可以发现他们都实现了List接口,它们使用起来非常相似.区别主要在于它们各自的实现,不同的实现导致了不同的性能和不同的操作. ArrayList是为可变数组实现的,当更多的元素添加到ArrayL

Java数据结构之表的增删对比---ArrayList与LinkedList之一

一.Java_Collections表的实现 与c不同Java已经实现并封装了现成的表数据结构,顺序表以及链表. 1.ArrayList是基于数组的实现,因此具有的特点是:1.有索引值方便查找,对于get和set操作花费常数时间,2.但是其缺点是:插入/删除某个数据的代价比较大. 2.LinkedList是基于双链表实现,因此具有的特点是:1.基于链表方便插入与删除操作开销较小,2.但是不方便索引,不管是索引哪一个元素都需要从头开始逐次查找. 就增删操作下面举个简单例子:给出一个表(具体实现未知

java的list几种实现方式的效率(ArrayList、LinkedList、Vector、Stack),以及 java时间戳的三种获取方式比较

一.list简介 List列表类,顺序存储任何对象(顺序不变),可重复. List是继承于Collection的接口,不能实例化.实例化可以用: ArrayList(实现动态数组),查询快(随意访问或顺序访问),增删慢.整体清空快,线程不同步(非线程安全).数组长度是可变的百分之五十延长 LinkedList(实现链表),查询慢,增删快. Vector(实现动态数组),都慢,被ArrayList替代.长度任意延长.线程安全(同步的类,函数都是synchronized) Stack(实现堆栈)继承

ArrayList和LinkedList的几种循环遍历方式及性能对比分析

主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论.通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解.阅读本文前希望你已经了解ArrayList顺序存储和LinkedList链式的结构,本文不对此进行介绍. 相关:HashMap循环遍历方式及其性能对

ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转)

主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解. 阅读本文前希望你已经了解ArrayList顺序存储和LinkedList链式的结构,本文不对此进行介绍. 相关:HashMap循环遍历方式及其性

ArrayList 和 LinkedList的执行效率比较

一.概念: 一般我们都知道ArrayList* 由一个数组后推得到的 List.作为一个常规用途的对象容器使用,用于替换原先的 Vector.允许我们快速访问元素,但在从列表中部插入和删除元素时,速度却嫌稍慢.一般只应该用ListIterator 对一个 ArrayList 进行向前和向后遍历,不要用它删除和插入元素:与 LinkedList 相比,它的效率要低许多LinkedList 提供优化的顺序访问性能,同时可以高效率地在列表中部进行插入和删除操作.但在进行随机访问时,速度却相当慢,此时应

【转】ArrayList和LinkedList的几种循环遍历方式及性能对比分析

原文网址:http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论.通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解.阅

ArrayList和LinkedList循环遍历效率探索(一)

一.Arraylist的遍历方式效率比较 实验代码: import java.util.ArrayList;import java.util.Iterator;import java.util.List; public class TestListSpeed { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); for (int index = 0; index <