java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析

目录

  • ArrayList
    • 底层结构
    • 源码分析
      • 无参构造器扩容机制源码分析
      • 有参构造器扩容机制源码分析
  • Vector
    • 底层结构
    • 源码分析
      • 扩容机制
  • LinkedList
    • 底层结构
    • 源码分析
  • 三者比较

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第1张图片
我们学习List下面ArrayList,LinkedList,Vector类即可!
学习的重点就是了解他们的底层结构,扩容原理,通过源码进行学习!

List接口下的一些常用方法
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第2张图片

@SuppressWarnings("all")
public class ArrayList_ {
    public static void main(String[] args) {
        List list = new ArrayList();
        //添加单个元素
        for (int i = 0; i <10; i++) {
            list.add(i);
        }
        //将list集合转换成数组进行打印!
        System.out.println(Arrays.toString(list.toArray()));
        //添加list集合
        List list1 = new ArrayList();
        list1.add(666);
        list1.add(888);
        //在1索引位置插入list1集合
        list.addAll(1,list1);
        //迭代器打印!
        Iterator iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next()+" ");
        }
        //删除元素
        list.remove(new Integer(666));
        //判断是否包含元素!
        list.contains(666);
        //删除整个list
        list.removeAll(list1);
        //返回最后一个9的下标位置!
        System.out.println("\n"+Arrays.toString(list.toArray()));
        System.out.println("从后往前找9的下标:"+list.lastIndexOf(9));
        System.out.println("6的下标:"+list.indexOf(6));
        System.out.println("拆分list集合");
        List tmp = list.subList(5,10);
        System.out.println("tmp:"+Arrays.toString(tmp.toArray()));
        //更改元素!
        System.out.println("更改前:"+list.get(0)+list.set(0,9)+"更改后:"+list.get(0));
        //排序:传入排序接口!
        System.out.println("排序前:"+Arrays.toString(list.toArray())+"\n排序后:");
        list.sort(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return (Integer) o1 - (Integer)o2;//升序
            }
        });
        //增强for遍历!
        for (Object object : list) {
            System.out.print(object+" ");
        }

    }

}

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第3张图片

ArrayList

底层结构

ArrayList底层是由数组实现的!
在这里插入图片描述

  • ArrayList维护了一个elementData数组,由transient修饰不可序列化!

  • ArrayList扩容机制:

    • 无参构造器,默认大小为0,第一次添加元素,扩容为10,后面扩容按照1.5倍进行
    • 有参构造器,默认容量指定参数值大小,不够进行1.5倍扩容

源码分析

我们通过IDEA调试从而分析ArrayList底层结构和扩容机制

无参构造器扩容机制源码分析

我们通过下面的代码进行ArrayList无参扩容机制的分析

public class ArrayList_ {
    public static void main(String[] args) {
        //无参扩容机制!
        ArrayList list = new ArrayList();
        //默认为 0 第一次添加扩容为 10
            for (int i = 0; i <10; i++) {
            list.add(i);
        }
        //后续扩容1.5!
        list.add(11);
    }
}
  • 无参构造器初始化elementData数组长度为0
    java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第4张图片
  • 第一次添加
    • 装箱,因为这里的数据是int基本类,要进行装箱成Integer类!

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第5张图片
第一次扩容
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第6张图片
进行扩容后elementData数组长度就变成了10
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第7张图片
当添加第11个元素时,进行二次扩容
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第8张图片

调用int newCapacity = oldCapacity + (oldCapacity>>1); 进行1.5倍扩容!
从而数组长度变成了15
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第9张图片

有参构造器扩容机制源码分析

public class ArrayList_1 {
        public static void main(String[] args) {
            //有参扩容机制,初始化指定容量大小
            ArrayList list = new ArrayList(5);
            for (int i = 0; i < 5; i++) {
                list.add(i);
            }
            //进行第一次1.5倍扩容
            list.add(6);
        }
    }
	

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第10张图片
总结:
每次add都会检查数组容量,是否要进行扩容!

  • 无参扩容机制

elementData数组默认为0,当进行第一次add进行第一次扩容,扩容大小为10,而后面进行二次扩容就是1.5倍扩容!

  • 有参扩容机制

elementData数组默认为指定参数长度,第一次扩容时,1.5倍扩容!

Vector

底层结构

Vector类和ArrayList类底层的结构一样也是数组!
不过和ArrayList区别就是,扩容策略不同,Vector是线程安全的(每个方法都加了synchronized),适用于多线程,而ArrayList线程不安全!

扩容策略

  • 无参构造器扩容策略,初始化容量为10,后续2倍扩容
  • 有参构造器,初始化指定参数容量,后续2倍扩容
  • 可设置增量的构造器,指定初始化容量,后续扩容按增量进行

源码分析

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第11张图片
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第12张图片
我们学习Vector构造方法后,发现Vector有个构造器,可以设置容量的增量!
可以自定义扩容的增量值!

扩容机制

通过下面的代码debug进行扩容机制的学习!

public class Vector_ {
    public static void main(String[] args) {
        //Vector无参扩容机制!
        Vector vector = new Vector();
        //一次扩容
        for (int i = 0; i <10 ; i++) {
            vector.add(i);
        }
        //进行二次扩容
        vector.add(10);
    }
}

无参构造器,初始化容量为10
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第13张图片
第一次扩容
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第14张图片
有参扩容机制和无参扩容机制类似,初始化时指定数组长度!扩容策略一样!

LinkedList

底层结构

LinkedList类和上述2个不同,他的底层采用的是双向链表的方式存储数据

  • LinkedList底层实现了双向链表和双端队列的特点
  • 可以添加任意元素包括null
  • 线程不安全,没有实现线程同步
  • 采用链表的方式存储,增删效率高,不需要扩容!

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第15张图片
可以看到LinkedList实现了List接口和DeQue接口!

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第16张图片
Node节点
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第17张图片

这里通过frist保存头Node节点,last保存尾节点!

因为LinkedList实现了Deque双端队列接口,所以其下的方法都实现了
java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第18张图片

方法使用

package list;
import java.util.Arrays;
import java.util.LinkedList;
public class LinkedList_ {
    public static void main(String[] args) {
        LinkedList linkedList = new LinkedList();
        linkedList.add(1);
        linkedList.addLast(2);
        linkedList.addFirst(0);
        System.out.println("获取队首元素:"+linkedList.getFirst());
        System.out.println("获取队尾元素:"+linkedList.getLast());
        System.out.println(Arrays.toString(linkedList.toArray()));
        System.out.println("出队:"+linkedList.poll());
        System.out.println(Arrays.toString(linkedList.toArray()));
        System.out.println("对尾删除元素:"+linkedList.pollLast());
        linkedList.push(12);
        linkedList.pop();
        System.out.println(Arrays.toString(linkedList.toArray()));
    }
}

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第19张图片
注意:

这里的方法有点多:offer/poll push/pop add/remove
这里只有push/pop不能进行First/Last组合,其他都可!

源码分析

 public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.remove();
        list.get(1);
    }

add添加节点

默认队尾入队

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第20张图片
remove删除节点

默认删除第一个节点!

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第21张图片
get方法获取节点

java集合专题List接口ArrayList/Vector/LinkedList底层结构和源码分析_第22张图片

三者比较

底层结构 增删效率 改查效率
ArrayList/Vector 可变数组 较低,要扩容 较高
LinkedList 双向链表 较高,通过链表修改指针即可 较低

三者如何抉择:

  • 如果改查操作多且单线程使用ArrayList,如果多线程就vector!
  • 如果增删操作多,那就LinkedList
  • 一般来说查询基本上查询为主,所以首选ArrayList!

你可能感兴趣的:(java集合,JAVA,java,list,数据结构)