Collection——List

List

存储特点:
	存储有序有索引,可重复的数据
	
List接口下常见的实现类:
	- ArrayList
	- Victor
	- LinkedList

ArrayList

List接口的主要实现类	---jdk1.2
底层结构:使用Object[] elementData存储
jdk 7情况下
	ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
jdk 8情况下
	ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没创建长度为10的数组
	list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
扩容方面jdk 7与jdk 8无异
	如果此次的添加导致底层elementData数组容量不够,则扩容。
	默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。

线程不安全的,运行效率高
查询快,增删慢

源码分析

// 默认容量(并不是创建集合时的容量)
private static final int DEFAULT_CAPACITY = 10;

private static final Object[] EMPTY_ELEMENTDATA = {};

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

// 存放元素的数组
transient Object[] elementData;

// 实际的元素个数
private int size;

// 无参构造器
public ArrayList() {
	// 没有向集合中添加元素时,容量为0
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

所以:ArrayList arrayList = new ArrayList<>();
此时的 size(实际元素个数)和 容量 都是0

add() 添加元素
arrayList.add(“番茄”);

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

// minCapacity = size + 1;	此时就是1
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

 private static int calculateCapacity(Object[] elementData, int minCapacity) {
 	// 为空,第一次判断成立
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    	// DEFAULT_CAPACITY为10,minCapacity为1,返回最大值10
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}   

// 返回值为10
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    
    // overflow-conscious code
    // minCapacity(10) - elementData.length(0) > 0 成立
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// 扩容代码
// minCapacity为10
private void grow(int minCapacity) {
    // overflow-conscious code
    // oldCapacity  = 0
    int oldCapacity = elementData.length;
    // newCapacity = 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 0 - 10 = -10 < 0 成立
    if (newCapacity - minCapacity < 0)
    	// minCapacity赋值给newCapacity,newCapacity变为10
        newCapacity = minCapacity;
    // 为负数,不成立	
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    // 复制指定数组(elementData为空,newCapacity为10),最后得到一个长度为10的 elementData 数组
    elementData = Arrays.copyOf(elementData, newCapacity);
}

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//Integer最大值-8

实例化结论:

当实例化一个ArrayList集合(空参),当没有添加元素时,容量为0;
但是当添加了第一个元素时,容量变为了10

当第二次添加元素,就会涉及到扩容问题

public boolean add(E e) {
	//此时size + 1 = 11
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

//minCapacity为11
private void ensureCapacityInternal(int minCapacity) {
	//elementData内有数据,minCapacity为11
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
	//elementData不为空,判断不成立
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    //直接返回minCapacity(11)
    return minCapacity;
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    //minCapacity(11) - elementData.length(10) > 0,成立
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// minCapacity为11
private void grow(int minCapacity) {
    // overflow-conscious code
    // oldCapacity 被 elementData.length 赋值为10
    int oldCapacity = elementData.length;
    // oldCapacity >> 1相当是除以2,所以 newCapacity 为15
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //15 - 11 < 0 不成立
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    //为负数,判断不成立
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    //复制数组,newCapacity为15,elementData原来的容量是10,此时容量变为15
    elementData = Arrays.copyOf(elementData, newCapacity);
}

扩容结论:

当再次添加了元素时,扩容为原来的1.5倍

建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)

Victor

古老的实现类		--jdk1.0
底层结构:使用Object[] elementData存储
jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。
在扩容方面,默认扩容为原来的数组长度的2倍。

线程安全的,运行效率低

LinkedList

底层结构:使用双向链表存储
	LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
	list.add(123);//将123封装到Node中,创建了Node对象。
	Node的定义:体现了LinkedList的双向链表
查询慢,增删快

源码分析

transient int size = 0;

//指向第一个元素的指针
transient Node<E> first;

//指向最后一个元素的指针
transient Node<E> last;

public LinkedList() {
}
public boolean add(E e) {
    linkLast(e);
    return true;
}

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

private static class Node<E> {
	//item 当前元素,实际的数据
    E item;
    //下一个节点
    Node<E> next;
    //上一个节点
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

第一次add
在这里插入图片描述
第二次add
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值