List和ArrayList

目录

List

在这里插入图片描述
常用方法:

方法 说明
public void add(int index,E element) 在指定的索引位置上添加数据
public E get(int index) 获取指定索引位置上的数据
public int indexOf(Object o) 查找指定对象的索引位置
public ListIterator listIterator() 获取ListIterator接口实例
public static List of(E …element) 通过指定的内容创建List集合
public E set(int index,E element) 修改指定索引位置上的数据
default void sort(Comparator<? super E> c) 实现List集合排序
List<String> list = List.of();			//使用of创建的List数组可以读,不可以改。(JDK1.9新增)
List<String> listA = new ArrayList<>();	//使用子类向上转型可以修改数据
List<String> listB = new LinkedList<>();//使用子类向上转型可以修改数据
List<String> listC = new Vector<>(); 	//使用子类向上转型可以修改数据

ArrayList

ArrayList使用数组的形式实现的,可以根据索引下标查询数据。

在这里插入图片描述
ArrayList无参构造源码:

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;	//默认初始容量为0
    }

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];

ArrayList有参构造源码:

public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
       this.elementData = new Object[initialCapacity];//大于0开辟一个传入数据大小的Object的数组
        } else {
            if (initialCapacity != 0) {
              throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
            }
            this.elementData = EMPTY_ELEMENTDATA;	//输入0,和无参构造一样
        }
    }

private static final Object[] EMPTY_ELEMENTDATA = new Object[0];

在使用add()、addAll()增加数据时在进行扩充操作。
在10或10以内用无参构造比较好,大于10用有参构造不然会产生垃圾空间。
add源码扩充的方法:

public boolean add(E e) {	
        ++this.modCount; //线程保护
        this.add(e, this.elementData, this.size);	
        return true;
    }

private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length) {	//判断数据的容量是否满了
            elementData = this.grow();	//容量扩充
        }

        elementData[s] = e;
        this.size = s + 1;
    }

    private Object[] grow() {
        return this.grow(this.size + 1);
    }

private Object[] grow(int minCapacity) {
        return this.elementData = Arrays.copyOf(this.elementData, this.newCapacity(minCapacity));	//copyOf改变ArrayList的容量赋给新的ArrayList数组
    }

//数组容量扩充
private int newCapacity(int minCapacity) {		
   int oldCapacity = this.elementData.length;  //获取前数组的长度
   int newCapacity = oldCapacity + (oldCapacity >> 1); //旧数据+新数据(旧数据右移1,相当于除2)
        if (newCapacity - minCapacity <= 0) {
            if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                return Math.max(10, minCapacity);	//第一次增加数据时ArrayList的容量变为10
            } else if (minCapacity < 0) {
                throw new OutOfMemoryError();
            } else {
                return minCapacity;
            }
        } else {
            return newCapacity - 2147483639 <= 0 ? newCapacity : hugeCapacity(minCapacity);
        }
    }

ArrayList扩容步骤:
1、ArrayList在未指定容量时,默认为0,而可以说容量为10

2、在第一次增加数据时,判断ArrayList的长度 == size,进行扩容操作。

3、使用Arrays.copyOf()保留原数组内容的同时进行数组扩容,改变容量长度。

4、在newCapacity()内,进行操作。
     1)获取数组长度。
     2)获取新的长度 newCapacity = (oldCapacity + (Capacity >>1)); 右移1 就是除2。

5、判定新的长度 - (传入的size + 1)<=0。

    1)判断数组是否容量为0,为0返回Math.max(10,传入的size + 1的值); 返回两个数的最大的那一个,第一次返回10。

​     2)小于0,报错。

     3)大于0,返回传入的size + 1的值。

6、判定 (新的长度 - (传入的size + 1)> 0) newCapacity - 2147483639(最大array的长度)<= 0 ? newCapacity : hugeCapacity(传入的size + 1的值);

LinkedList

LinkedList使用链表的形式实现数据的存储,但查询的性能不高。
在这里插入图片描述

Vector

Vector的实现和ArrayList类似,但使用率极低。
在这里插入图片描述
Vector默认容量为10:

 public Vector() {
        this(10);
    }

区别

ArrayList: 在JDK1.2提出加入集合类,基于数组实现的动态数据存储,根据索引查询的时间复杂度为O(1),内部未使用线程同步,属于非线程安全。

LinkedList: 在JDK1.2提出加入集合类,基于链表实现数据存储,根据索引查询的时间复杂度为O(n)。

Vector: 在JDK1.0提出的一个类,在JDK1.2加入集合类,基于数组实现的动态数据存储,内部方法使用了synchronized同步,属于线程安全。

发布了61 篇原创文章 · 获赞 0 · 访问量 2183

猜你喜欢

转载自blog.csdn.net/sabstarb/article/details/104584363
今日推荐