Java的list集合总结

时间:2024-07-19 09:03:42

在编程语言中,我们必然少不了存储数据的容器,虽然我们有数组,但是数组是连续的开辟处一块连续的内存空间,我们的数据过大会无法存储完,数据量小,会浪费空间,所以我们需要使用集合存储数据,而在Java中list和set是我们最常用的集合,它们都属于Collection接口的子接口,那么我们下面分析其共同点,和其对应的数据结构。

1.list接口:

        首先list接口,作为单列集合(只存储值),它允许值重复(值可以不唯一)。它的实现类有Arraylist,linkedList,Vector

        从线程安全的角度,我们逐个分析:

        线程不安全:

                ArrayList:

                1.数据结构:Object数组,观察源码可知,其底层逻辑还是以Object,数组存放数据

                2.扩容方式:

                        首先我们需要知道,集合比数组的优势之一就是其内存储空间可变化,那么它是如何变化的,而且它的数据结构是一个Object数组,但数组并没有完成初始化,又在什么时候完成初始化。且容量不足时又如何扩容呢。它们都与其内部定义的成员变量(默认数组),以及无参,有参构造方法,add()方法有关,下面我们先观察源码(扩容的源码没有展示)

                内部定义的成员变量与数组:

                无参构造方法   源码:

                有参构造方法  源码:

                add()方法:

                结论:无参构造方法:观察源码可知,它的构造方法是在内部将默认的数组初始化,但长度为0,当我们调用add()方法添加第一个元素时,它就会调用内部的参数,将数组的长度扩容为10,当容量不足时,就会以现数组容量的1.5倍进行扩容。
                        有参构造方法:观察源码可知,其有参构造方法是根据参数,将内部数组初始化长度(适用于预估数据量创建),当容量不足时,我们的数组容量也是以现数组容量的1.5倍进行扩容
                使用场景:相对来说,其内部存储空间连续,格局下标获取元素,适合查找,遍历,
                        不适合插入,删除,当删除和插入到中间或者头部元素时,其需要复制数组内容,再删除或插入,消耗性能。包含调用add的重载方法,根据下标插入等

        LinkedList:

                1.数据结构:观察源码可知,其内部为一条双向的链表

    

                2.扩容方式:观察源码可知,当我们调用add方法添加元素时,其就会动态的添加一个节点,链表动态的扩容,并且如果是add()方法,或者 addLast()方法添加到链表尾部(尾插法),如果是addFirst()方法就是动态添加到头部(头插法)。

                此类为我们提供了不同参数的add方法,也可根据参数,动态的将元素添加到任意位置

        

                使用场景:相对来说插入,删除效率高,查找效率低,但是查找头元素,尾元素效率极高。

         线程安全:Vector,Stack

                Vector:

                    1.数据结构:

                        无参构造,和有参构造方法

                结论:观察源码可知,其内部也是数组
                    2.扩容方式:

                                观察上述源码,我们可知

                                无参构造,或单个参数有参构造:其内部数组初始容量为10,当容量不足时,我们按数组现有容量的两倍进行扩容。

                                两个参数有参构造:

                                参数一:设定了数组初始容量的值,参数二:规定了数组容量扩容值。

                    3.线程安全: 观察其内部的多个方法,我们可知,其内部不同的方法都加上了synchronized,锁所以保证线程安全。

                                          Stack:观察源码可知,Stack类继承自Vector类,Stack(栈)本身就是一种数据存储结构,其最大特点就是先进后出FILO。

最后,list接口的实现类包含了多种,还有CopyOnWriterArrayList等,在此就不逐一介绍了。