ArrayList与LinkedList区别

Posted 敲代码的小小酥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList与LinkedList区别相关的知识,希望对你有一定的参考价值。

ArraysList和LinkedList都是java中存放数据的集合。那么这两者都在什么场景下使用呢?

ArraysList

ArraysList底层实现是数组,数组结构的特点是增删慢、查询快。这里的增删慢指不是在尾部增删数据慢,而是在非尾部增删数据慢。因为ArrayList的底层实现是新建立一个数组,然后通过copy操作来复制数据,从而达到增删数据的效果。这个copy操作,就浪费了性能。

ArrayList可以指定容量。如果不指定容量,那么初始容量为0。当第一次调用add方法添加元素的时候,扩容到10。此后再需要扩容的时候,按照原来1.5倍空间进行扩容。扩容的本质也是新建一个数组,然后copy数据进行扩容。也很浪费性能。因此可以规定初始容量,减少ArrayList的扩容触发。

参考文章:浅谈ArrayList及其扩容机制

LinkedList


由源码可以看到,LinkedList内部维护了first和last头部和尾部节点。每个节点Node还维护了next和prev上一个和下一个节点。其是一个双向链表。链表的特点是查询慢,增删快。因为维护了上一个Node和下一个Node,所以增删就是对Node指针的改变,不需要进行数据的copy等操作,所以增删快。因为链表中没有角标索引,所以查询起来速度慢。

LinkedList没有最大容量个初始容量,也不需要扩容,理论只要内存够大,可以存无限的值。所以扩容带来的性能损耗都没有。

参考文章:linkedList详解

实际应用

在一个数据量大,数据传输频繁的场景中,需要用一个集合接收传输的数据,然后再用另外一个线程去消费集合中接收到的数据。要求先进先出,先消费集合前面的数据,再消费集合后面的元素。

上述场景中应该选择哪个集合呢?通过分析可以发现,添加元素都是往集合的尾部添加,所以ArrayList和LinkedList都可以,性能都不受影响。而消费数据是从集合头部开始消费的,因为数据量大,传输频繁,所以这里需要消费完一个数据,就删除一个数据,避免造成内存空间的浪费。那么删除数据,用哪个快呢?肯定是用LinkedList更快。因为这里不涉及到数据的查询,就是消费集合中的第一个元素,所以LinkedList查询慢的弊端在这里显现不出来。
此外,数量大,数据传输频繁,那么ArrayList很可能会触发扩容机制而影响性能,所以这里使用LinkedList更合适。

下面通过实验证明:

public static void main(String[] args) 
        //使用ArrayList
        ArrayList list=new ArrayList();
        //启动线程添加数据,添加一百万条数据
        new Thread()
            @Override
            public void run() 
                for (int i=0;i<1000000;i++)
                    list.add(i);
                    logger.error("add:"+i);
                
            
        .start();
        //另一个线程消费数据,当消费完成后退出循环,并打印消费的数据
        new Thread()
            @Override
            public void run() 
                while (true)

                try 
                    Object remove = list.remove(0);
                    logger.error("data:" + remove);
                catch (Exception e)
                   break;
                

                
            
        .start();

    

通过日志可以看到开始消费的时间为13:19:41.928,结束消费的时间为13:21:39.505,将近两分钟。

改成用LinkedList:

public static void main(String[] args) 
        //使用ArrayList
        LinkedList list=new LinkedList();
        //启动线程添加数据,添加一百万条数据
        new Thread()
            @Override
            public void run() 
                for (int i=0;i<1000000;i++)
                    list.add(i);
                    logger.error("add:"+i);
                
            
        .start();
        //另一个线程消费数据,当消费完成后退出循环,并打印消费的数据
        new Thread()
            @Override
            public void run() 
                while (true)

                try 
                    Object remove = list.remove(0);
                    logger.error("data:" + remove);
                catch (Exception e)
                   break;
                

                
            
        .start();

    

通过日志发现开始消费和结束消费的时间为22秒左右。可见LinkedList更适合该场景。

以上是关于ArrayList与LinkedList区别的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList与LinkedList的区别 ?

arraylist和linkedlist重大区别?

Java面试题:ArrayList和LinkedList的区别

在Java中ArrayList、LinkedList、HashMap的区别是啥

在Java中ArrayList、LinkedList、HashMap的区别是啥

第302天学习打卡(知识点回顾 arraylist 和 linkedlist 区别)