ArrayList与LinkedList区别

本文对比了ArrayList和LinkedList在Java中的适用场景,阐述了ArrayList的数组结构导致的增删效率低和可能的频繁扩容问题,以及LinkedList作为链表结构在查询上的劣势但增删快速。在数据量大、频繁传输且需要FIFO的场景中,LinkedList由于删除操作优势明显,更适合这种需求。
摘要由CSDN通过智能技术生成

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更适合该场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码的小小酥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值