List集合知识点梳理

文章详细介绍了Java中List接口的两个主要实现类ArrayList和LinkedList的特点。ArrayList基于数组实现,适合多读少增删的场景,而LinkedList采用双链表,适合多增删少读写。ArrayList的扩容是原容量的1.5倍,LinkedList存储空间消耗较大。此外,还提到了线程安全的Vector类和List的常用操作方法。
摘要由CSDN通过智能技术生成

概述

        List是有序集合(这里的有序指元素存入和取出的顺序相同,而不是按照元素的特性排序),可以存储重复的元素,可以存入多个null值。List集合是工作中最常用的类,相比数组,集合的长度可变,更加方便开发。List主要有两个实现类ArrayList、LilnkedList。

常用List集合的实现类

ArrayList

        ArrayList数组是底层由数组实现的有序集合,与Array数组不同的是,Array可以包含基本类型和对象类型的数据,大小是固定的。但ArrayList只能包含对象类型,大小是动态变化的,相比Array有更多的内置方法,如addAll(),removeAll()。针对基本数据类型,ArrayList使用自动装箱来减少编码的工作量,但是如果这个基本类型的数据大小固定,使用Array更加高效。

        ArrayList不保证线程安全,可以插入null值,初始容量是10,每次扩容后都是原来的1.5倍,所以存在一定的空间浪费。由于底层是数组,所以插入和删除元素的时间复杂度会收到位置的影响,而读取元素的时候可以直接根据下标查找到元素,不受位置影响,所以更加适用于多读少增删的场景。

ArrayList的扩容机制

        ArraList调用无参构造方法时创建的是一个长度为0的空数组,当调用add()方法添加元素时才会触发扩容机制。扩容时先将旧容量右移一位(位运算),加上旧容量就得到了新容量,右移一位相当于除以2,在此基础上加上旧容量就等价于新容量=旧容量*1.5,因此我们说ArrayList每次扩容都是原来的1.5倍。扩容后调用Arrays.copyOf()方法进行拷贝,并将引用指向新数组,此时旧数组因为没有引用指向,很快会被垃圾回收器回收。

LilnkedList

        LinkedList底层是通过双线链表来实现的,随着元素的增加不断的向链表中增加节点,每次顺序插入元素时都会new一个对象。存储元素的时候要存放直接后继,直接前去以及数据,所以空间消耗比ArrayLlist大。LinkedList插入和删除元素不受位置的影响,如果要在指定位置插入元素的时间复杂度为O(n),因为插入元素前需要先找到指定的位置。由于底层是双线链表,每个节点都拥有指向前后节点的引用,增加了元素检索的效率,因此适用于多增删,少读写的场景。

Vector

        vector相当于具有同步机制的ArrayList,通过Synchronized来实现线程同步,是线程安全的,但也因为加了同步锁,性能方面反而不如ArrayList。扩容时每次都是旧容量的两倍。

List集合的常用方法

        add(index,obj):在指定位置添加元素
        remove(index):删除元素并返回
        set(index,obj):将指定位置的元素更改为指定值并返回修改前的值
        indexOf(obj):返回指定元素在集合中第一次出现的位置
        get(index):返回指定位置的元素
        subList(fromIdex,toIndex):从指定位置截取元素,左闭右开

LinkedList的常用方法

        addFirst():往头部添加元素

        addLast():往尾部添加元素

        removeFirst():在头部删除元素

        removelast():在尾部删除元素

        getFirst():获取头部元素

        getLast()   :获取尾部元素

List集合储存元素的方式和遍历

        常见元素在内存中的存储方式主要有两种:

        1、顺序存储:相邻的数据元素在内存中的位置也是相邻的,可以根据元素的位置读取元素(如ArrayList的下标)。

        2、链式存储:每个元素都包含它下一个元素的内存地址,在内存中不要求相邻,如LinkedList。

List集合的主要遍历方式:

        1、for循环:遍历者在集合外部维护一个计数器,依次读取每一个位置的元素;

        2、Iterator遍历:基于顺序存储的集合迭代器可以按照位置直接访问数据,基于链式存储的集合,迭代器需要先保存当前遍历的位置,然后根据当前位置来向前或向后移动指针。

        3、foreach遍历:foreach内部也是采用Iterator的方式实现的,但是使用的时候不需要显示声明Iterator。

        Java集合框架提供了RandomAccess接口,这个接口没有方法,只是一个标记,通常情况下用它来标记list的实现是否支持RandomAccess。所以遍历的时候,可以通过这个标记来判断选用哪种遍历方式,如果(list instanceof RandomAccess)支持就选用for循环遍历,不支持的情况下建议使用迭代器或foreach循环遍历。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值