ArrayList LinkedList Vector原码分析

 ArrayList的原码分析

package list;

import java.util.ArrayList;

/**
 * ArrayList原码分析
 * 总结一下:ArrayList的底层主要就是维护了一个elementData[]这样一个数组。
 * 在我们new ArrayList的时候,这个时候我们的elementData[]还是一个空的数组,
 * 当我们第一次调用add方法的时候,我们的elementData[]就会扩容成一个大小为10
 * 的数组,当我们添加第11个数字的时候,又再次发生的扩容,扩容的大小为
 * (oldCapacity + oldCapacity/2)。
 * 在我们new ArrayList的时候,我们也可以指定初始大小;还可以传一个相同类型的数组
 *
 * 优点:它是根据索引来查询的,所以查找速度也很快。顺序添加也是很方便的。
 * 缺点:在从中间删除和插入的时候,就会引起整个数组的变化,会进行数组元素的复制,很浪费时间。
 */
public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.get(2);
    }
    /**
     * 在我们new一个ArrayList的时候,我们会给这个容器赋一个初始值,为空
     * private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
     *
     * 这里我们可以看到这个elementData的值为空
     * public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
     *
     * 一个返回值为boolean类型的add方法
     *     public boolean add(E e) {
     *         判断是否需要扩容
     *         ensureCapacityInternal(size + 1);  // Increments modCount!!
     *         将值存储到size位置,并且size++
     *         elementData[size++] = e;
     *         return true;
     *     }
     *
     * 首先我们会进入 ensureCapacityInternal这个函数,
     * 然后会判断elementData和DEFAULTCAPACITY_EMPTY_ELEMENTDATA是否相等,
     * 如果相等就会给我们的容器给大小DEFAULT_CAPACITY的值为10,所以我们的
     * 初始容量大小就为10(就是我们第一次使用add方法的时候)
     *     private void ensureCapacityInternal(int minCapacity) {
     *         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
     *             minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
     *         }
     *         ensureExplicitCapacity(minCapacity);
     *     }
     *
     * ensureExplicitCapacity这个方法就是判断是否需要扩容,我们扩容的具体
     * 操作就在我们的grow中,当我们的 minCapacity - elementData.length > 0 
     * 的时候,就需要扩容了
     *     private void ensureExplicitCapacity(int minCapacity) {
     *
     *     这个modCount++主要就是防止在多线程插入的时候,
     *     可能会出现并发修改异常的状况。ConcurrentModificationException
     *         modCount++;
     *
     *         // overflow-conscious code
     *         if (minCapacity - elementData.length > 0)
     *             grow(minCapacity);
     *     }
     *
     * 这个就是我们具体的扩容操作了
     *     private void grow(int minCapacity) {
     *         // overflow-conscious code
     *
     *         首先将我们的数组长度赋给oldCapacity
     *         int oldCapacity = elementData.length;
     *
     *         然后扩容,具体扩容大小为 oldCapacity + oldCapacity/2
     *         int newCapacity = oldCapacity + (oldCapacity >> 1);
     *
     *         然后判断这个新的Capacity是否比我们的允许的最小容器大小都还要小,
     *         如果是,那么就让它等于最小的容器大小(minCapacity)
     *         if (newCapacity - minCapacity < 0)
     *             newCapacity = minCapacity;
     *
     *         如果都大于数组允许的最大大小了
     *         (MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8,Integer.MAX_VALUE=2^31-1)
     *         那么就让newCapacity=数组的最大值
     *         if (newCapacity - MAX_ARRAY_SIZE > 0)
     *             newCapacity = hugeCapacity(minCapacity);
     *         // minCapacity is usually close to size, so this is a win:
     *
     *         最后就是将我们原来的数组(elementData)复制到我们的新的数组中(newCapacity)
     *         然后将最终结果存储到elementData中。
     *         elementData = Arrays.copyOf(elementData, newCapacity);
     *     }
     *     private static int hugeCapacity(int minCapacity) {
     *         if (minCapacity < 0) // overflow
     *             throw new OutOfMemoryError();
     *         return (minCapacity > MAX_ARRAY_SIZE) ?
     *             Integer.MAX_VALUE :
     *             MAX_ARRAY_SIZE;
     *     }
     */
}




LinkedList的源码分析

package list;

import java.util.LinkedList;
import java.util.Vector;

/**
 * LinkedList的原码分析
 * 总结一下:LinkedList的底层主要就是维护了一个双向链表。
 * 我们可以定位的插入,可以从头插入(linkedList.addFirst()),
 * 也可以从尾部插入(linkedList.addLast())
 *
 * 优点:它的添加是非常快的
 * 缺点:删除,查询都是需要从头结点或者尾结点开始遍历这个链表的
 * (当然只会遍历链表长度的一半,看下面的node原码就知道了),
 * 包括我们的插入都是如此。
 */
public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<String> linkedList=new LinkedList<>();
        linkedList.add("a");
        linkedList.add("b");
        linkedList.add("c");
        linkedList.add("d");
        linkedList.add("e");
        linkedList.add(3,"f");
        linkedList.get(4);
        linkedList.remove(2);
        System.out.println(linkedList.size());

    }

    /**
     * 在new LinkedList的时候,如果不传任何参数,就默认走空参的构造方法
     *     public LinkedList() {
     *     }
     *
     * 开始add方法
     *     public boolean add(E e) {
     *         linkLast(e);
     *         return true;
     *     }
     *
     * 在尾部开始添加数据
     *     void linkLast(E e) {
     *     
     * 在我们添加第一个数据的时候,l = null
     *         final Node<E> l = last;
     *         
     * 将我们当前的数据存入一个新的节点中,它的前一个节点为l,
     * 后一个节点为null(因为是在尾部插入嘛)
     *         final Node<E> newNode = new Node<>(l, e, null);
     *         
     * 将newNode 赋值给l,为下一个节点插入做准备
     *         last = newNode;
     *         
     * 如果l=null(就是第一次插入节点)
     *         if (l == null)
     *         
     * 将头结点定位当前插入的这个节点
     *             first = newNode;
     *         else
     *         
     * 否则,当前节点就是l的下一个节点。
     *             l.next = newNode;
     *             
     * size++计数,我们的linkedList.size()等等都会用到这个size
     *         size++;
     *         modCount++;
     *     }
     *
     * 这是linkedList的remove方法,其实就是从头遍历整个链表,
     * 然后找到那个匹配的数字,然后unlink就可以了
     *     public boolean remove(Object o) {
     *         if (o == null) {
     *             for (Node<E> x = first; x != null; x = x.next) {
     *                 if (x.item == null) {
     *                     unlink(x);
     *                     return true;
     *                 }
     *             }
     *         } else {
     *             for (Node<E> x = first; x != null; x = x.next) {
     *                 if (o.equals(x.item)) {
     *                     unlink(x);
     *                     return true;
     *                 }
     *             }
     *         }
     *         return false;
     *     }
     *
     * unlink方法
     *     E unlink(Node<E> x) {
     *         // assert x != null;
     *         final E element = x.item;
     *         final Node<E> next = x.next;
     *         final Node<E> prev = x.prev;
     *
     *         if (prev == null) {
     *             first = next;
     *         } else {
     *             prev.next = next;
     *             x.prev = null;
     *         }
     *
     *         if (next == null) {
     *             last = prev;
     *         } else {
     *             next.prev = prev;
     *             x.next = null;
     *         }
     *
     *         x.item = null;
     *         size--;
     *         modCount++;
     *         return element;
     *     }
     *
     *
     * 在我们非顺序添加的时候
     *     public void add(int index, E element) {
     *         checkPositionIndex(index);
     *
     *         if (index == size)
     *             linkLast(element);
     *         else
     *
     *         //非顺序添加
     *             linkBefore(element, node(index));
     *     }
     *
     * 我们可以看到,在进行非顺序添加(插入)的时候,
     * 我们会从头结点或者尾结点开始查找。查找也是这样
     *     Node<E> node(int index) {
     *         // assert isElementIndex(index);
     *
     *         if (index < (size >> 1)) {
     *             Node<E> x = first;
     *             for (int i = 0; i < index; i++)
     *                 x = x.next;
     *             return x;
     *         } else {
     *             Node<E> x = last;
     *             for (int i = size - 1; i > index; i--)
     *                 x = x.prev;
     *             return x;
     *         }
     *     }
     */

}

Vector原码分析

package list;

import java.util.Vector;

/**
 * Vector原码
 * 总结:其实Vector的原码和我们的ArrayList差不多,
 * 就是它在每一个方法上面都添加了synchronized。保证了线程安全
 * 还有一点值得注意的就是它是在new Vector<>()的时候就已经给好了初始值(默认10)。
 */
public class VectorDemo {
    public static void main(String[] args) {
        Vector<String> vector = new Vector<>();
        vector.add("a");
        vector.add("b");
        vector.add("c");
        vector.add("d");
    }

    /**
     *     public synchronized boolean add(E e) {
     *         modCount++;
     *         ensureCapacityHelper(elementCount + 1);
     *         elementData[elementCount++] = e;
     *         return true;
     *     }
     */
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值