容器1(Collection,set,list接口介绍、ArrayList底层源码分析、LinkedList源码分析、Vector和ArrayList的区别)

一、 Collection、set、list接口介绍

数组的优势:是一种简单的线性序列,可以快速地访问数组元素,效率高。如果从效率和类型检查的角度讲,数组是最好的。
数组的劣势:不灵活。容量需要事先定义好,不能随着需求的变化而扩容。
在这里插入图片描述
各接口的特点
Collection 接口存储一组不唯一,无序的对象
List 接口存储一组不唯一,有序(索引顺序)的对象
Set 接口存储一组唯一,无序的对象
map:每次存储 key-value对、 key部分不能重复、 常用实现类HashMap或TreeMap

1.Collection下的方法

在这里插入图片描述

  1. size():返回集合中元素的个数
  2. isEmpty():如果集合中没有元素,则返回true
  3. contains():是一个多态方法。如果此集合中包含指定的元素则返回true
  4. iterator():是继承自Iterable接口中的方法,继承了该接口可以使用foreach便利元素
  5. toArray():将集合对象转成一个Object类型的数组
  6. add():添加一个元素到集合中,添加成功则返回true
  7. remove():从集合中删除一个指定的对象
  8. containsAll(Collection<?> c):当前集合中是否包含了集合c的所有元素
  9. addAll(Collection<? extends E> c);将一个集合中的元素添加到指定的集合中
  10. removeAll(Collection<?> c); 删除一个集合中的所有元素
  11. retainAll(Collection<?> c);删除和C集合中非相交的部分
  12. clear();清空集合
  13. equals(Object o):用于计较两个集合中的对象的内容是否相等

2.Set中定义的方法

set接口中定义的都是Collectiond父接口中的方法
在这里插入图片描述

3.List中的方法

list接口中定义了一些自定义的方法
在这里插入图片描述

  1. boolean addAll(int index, Collection<? extends E> c):在指定的位置添加c集合中的全部元素
  2. get(int index);获取指定下标的位置获取元素对象
  3. set(int index, E element):将集合中(index)下标位置设置指定的对象(element)
  4. add(int index, E element):在指定的位置(index)添加一个元素对象(element)
  5. remove(int index):删除集合中指定位置(index)的对象.
  6. indexOf(Object o):查找集合中第一个元素对象(object)的下标,若找不到则返回-1。
  7. lastIndexOf(Object o):查找集合中最后一个元素对象(object)的下标,若找不到则返回-1。
  8. ListIterator listIterator():返回此列表中元素列表的迭代器

二、ArrayList使用方法及底层源码分析

1.ArrayList的使用方法

		 //无参构造
        ArrayList list0 = new ArrayList();
        //指定初始空间大小的有参构造
        ArrayList list = new ArrayList(20);
        //Add方法
        list.add("123");
        //set方法
        list.set(0, "hello world");
        //是否为空
        list.isEmpty();
        //移除指定下标的元素
        list.remove(1);
        //清空
        list.clear();
        //迭代器
        Iterator iterator = list.iterator();
        if (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }

2.ArrayList底层源码分析

[1] 无参构造
(1)无参构造方法
  this.elementData是一个object类型的一维数组。
  DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个静态object类型常量
  DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};默认长度为0,但是在堆中开辟了空间

   public ArrayList() {
          this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
          相当于this.elementData ={};
     }
[2] 有参构造
public ArrayList(int initialCapacity) {//初始容量参数
          if (initialCapacity > 0) {//若参数>0,则new Object[初始容量参数],把这个对象赋值给this.elementData
              this.elementData = new Object[initialCapacity];
          } else if (initialCapacity == 0) {//若初始容量参数为0,则将一个Object[]={}赋值给this.elementData
              this.elementData = EMPTY_ELEMENTDATA;
          } else {//若是一个复数,则抛出异常
              throw new IllegalArgumentException("Illegal Capacity: "+
                                                 initialCapacity);
          }
      }
[3] add方法
*	public boolean add(E e) {
 *         ensureCapacityInternal(size + 1);  // 检测空间容量是否够用,若size+1超出了数组容量,则会自动扩容
 *         elementData[size++] = e;//elementData[size] = e; size++;(数组下标从0开始)
 *         return true;
 *     }
 *  public void add(int index, E element) {
 *         rangeCheckForAdd(index);//检查下标是否越界,若下标 < 0 或下标 > size,则抛出异常
 *
 *         ensureCapacityInternal(size + 1);  // 检测空间容量是否够用,若size+1超出了数组容量,则会自动扩容
 *         
 *         //从elementData[index]开始拷贝,拷贝到elementData[index+1],拷贝长度为size-index,即把index及之后的元素后移一位
 *         System.arraycopy(elementData, index, elementData, index + 1,
 *                          size - index);
 *         elementData[index] = element;//把element赋值给elementData[index]
 *         size++;
 *     }
 * 检测空间容量是否够用
 * private void ensureCapacityInternal(int minCapacity) {//参数:最小空间容量
 *         ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
 *     }
 *
 *     //该函数作用:若当前数组为空数组,则返回10和最小空间容量中较大的数。若当前数组不为空数组,则直接返回最小空间容量
 *  private static int calculateCapacity(Object[] elementData, int minCapacity) {
 *         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//若当前数组=={}
 *             return Math.max(DEFAULT_CAPACITY, minCapacity);//返回 max(10,最小空间容量)。
 *         }
 *         //否则返回最小空间容量
 *         return minCapacity;
 *     }
 *  private void ensureExplicitCapacity(int minCapacity) {
 *         modCount++;
 *        //若最小空间容量 > elementData数组的长度,则执行扩容函数grow
 *         if (minCapacity - elementData.length > 0)
 *             grow(minCapacity);//执行扩容
 *     }
[5] 扩容方法
private void grow(int minCapacity) {
 *
 *         int oldCapacity = elementData.length;//旧容量 = elementData数组的长度
 *         int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量=1.5倍旧容量。(>>1即为 除2 )
 *         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:
 *         //把旧数组拷贝到新数组,在将新数组赋值给elementData
 *         elementData = Arrays.copyOf(elementData, newCapacity);
 *     }
[6] get方法
 *  public E get(int index) {
 *         rangeCheck(index);//检测下标是否合法。若index>=size,则抛出异常
 *
 *         return elementData(index);//返回elementData[index]
 *     }
[7] set(index,element)方法
 *   public E set(int index, E element) {
 *         rangeCheck(index);//检查下标是否合法
 *
 *         E oldValue = elementData(index);//把原来的值赋值给oldValue
 *         elementData[index] = element;//把element赋值给elementData[index]
 *         return oldValue;//返回旧值
 *     }
[8] isEmpty()
 *  public boolean isEmpty() {
 *         return size == 0;
 *     }
[9] remove()
 *  public E remove(int index) {
 *         rangeCheck(index);
 *         modCount++;
 *
 *         E oldValue = elementData(index);//把被删除的元素赋值给oldValue
 *
 *         int numMoved = size - index - 1;//数组中元素需要被移动的个数 = size - index-1
 *         if (numMoved > 0)//若需要移动的个数 > 0
 * //则调用数组拷贝函数。从elementData数组中下标为index+1开始拷贝,拷贝到elementData数组本身,
 *  //起始位置为index,拷贝元素个数为numMoved
 *             System.arraycopy(elementData, index+1, elementData, index,
 *                              numMoved);
 *         elementData[--size] = null; // 把elementData[size-1]=null;size--
 *
 *         return oldValue;//返回oldValue
 *     }
[10] clear()
 *  public void clear() {
 *         modCount++;
 *
 *         // 用for循环将elementData中的值全部赋值为null,size=0
 *         for (int i = 0; i < size; i++)
 *             elementData[i] = null;
 *         size = 0;
 *     }
[11] iterator()
 *   public Iterator<E> iterator() {
 *         return new Itr();
 *     }
 *
 *    private class Itr implements Iterator<E> {
 *         int cursor;       // 指针
 *         int lastRet = -1; // index of last element returned; -1 if no such
 *         int expectedModCount = modCount;
 *
 *         Itr() {}
 *
 *         public boolean hasNext() {
 *             return cursor != size;
 *         }
 *
 *         public E next() {
 *             checkForComodification();
 *             int i = cursor;//把指针赋值给i
 *             //保证代码的健壮性
 *             if (i >= size)
 *                 throw new NoSuchElementException();
 *
 *             //把ArrayList中的elementData赋值给新定义的elementData
 *             Object[] elementData = ArrayList.this.elementData;
 *             //保证代码的健壮性
 *             if (i >= elementData.length)
 *                 throw new ConcurrentModificationException();
 *             //指针=i+1
 *             cursor = i + 1;
 *             返回elementData[i]
 *             return (E) elementData[lastRet = i];
 *         }
 */

三、LinkedList源码分析

1.ArrayList和LinkedList 的区别

ArrayList:底层为数组,查询快,增删慢
LinkedList:底层为Node节点,查询慢,增删快
在这里插入图片描述
Node类

private static class Node<E> {
        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;
        }
    }

2.LinkedList源码分析

LinkedList list = new LinkedList();
        list.add("java");
        list.add(1,"hello");
        list.addFirst("hello");
        list.addLast("world");
        list.remove();
        list.remove("world");
        list.remove(1);
        list.removeFirst();
        list.removeLast();
        list.clear();
[1]无参构造
public LinkedList() {
      }
[2]add方法:add()、add(index,element)
 *(1) public boolean add(E e) {
 *         linkLast(e);
 *         return true;
 *     }
 *
 *(2)public void add(int index, E element) {
 *         checkPositionIndex(index);//检查下标是否越界
 *         if (index == size)//若该节点添加到尾部
 *             linkLast(element);
 *         else
 *             linkBefore(element, node(index));//node(index)返回的是指定索引处的节点
 *     }
 *     transient Node<E> first;//头结点
 *     transient Node<E> last;//尾节点
 *      void linkLast(E e) {
 *         final Node<E> l = last;
 *         final Node<E> newNode = new Node<>(l, e, null);//定义一个新的节点,前驱节点为l,元素为e,后驱节点为null
 *         last = newNode;//把newNode赋值给last
 *         if (l == null)//若l(原来的last)节点为null,即节点中没有值
 *             first = newNode;//把newNode赋值给first节点
 *         else //否则,把旧的尾节点的下一个节点赋值为newNode
 *             l.next = newNode;
 *         size++;
 *         modCount++;
 *     }
 *
 *     //e为节点内容,succ为指定索引的非空节点
 *     void linkBefore(E e, Node<E> succ) {
 *         // assert succ != null;
 *         final Node<E> pred = succ.prev;//succ的前置节点赋值给pred节点
 *         final Node<E> newNode = new Node<>(pred, e, succ);//创建一个新的节点,前置对象为pred,后置对象为succ
 *         succ.prev = newNode;//把succ的前置节点指向newNode
 *         if (pred == null)//若指定索引的节点无前置节点,则newNode为头结点
 *             first = newNode;
 *         else //否则,把pred的下一个节点指向newNode
 *             pred.next = newNode;
 *         size++;
 *         modCount++;
 *     }
 *
[3]addFirst()
*  public void addFirst(E e) {
 *         linkFirst(e);
 *     }
 *  private void linkFirst(E e) {
 *         final Node<E> f = first; //把头结点复制给 f
 *         final Node<E> newNode = new Node<>(null, e, f);//创建一个新节点,前置节点为null,后置节点指向f
 *         first = newNode;//把newNode赋值给节点first
 *         if (f == null)//若f为null,即插入节点前,该节点是空节点
 *             last = newNode;//把newNode赋值给last
 *         else //若不为空,则把f的前置节点指向newNode
 *             f.prev = newNode;
 *         size++;
 *         modCount++;
 *     }
 *
[4]addLast()
 *  public void addLast(E e) {
 *         linkLast(e);
 *     }
 *     void linkLast(E e) {
 *         final Node<E> l = last; //把尾节点last赋值给l节点
 *         final Node<E> newNode = new Node<>(l, e, null);//创建一个新节点,前置节点指向l,尾节点指向null
 *         last = newNode;  //把尾节点赋值给last
 *         if (l == null)   //若last为null,即插入前节点为空,则把first也赋值为newNode
 *             first = newNode;
 *         else //若不为Null,则把 l节点的后置节点指向newNode
 *             l.next = newNode;
 *         size++;
 *         modCount++;
 *     }
[5]remove()、 removeFirst()
 *  public E remove() {
 *         return removeFirst();
 *     }
 *   public E removeFirst() {
 *         final Node<E> f = first;
 *         if (f == null)
 *             throw new NoSuchElementException();
 *         return unlinkFirst(f);
 *     }
 *   private E unlinkFirst(Node<E> f) {
 *         // assert f == first && f != null;
 *         final E element = f.item;//把first存储的元素赋值给element
 *         final Node<E> next = f.next;//把first的下一个节点赋值为next
 *         f.item = null;
 *         f.next = null; // 清空头结点
 *         first = next; //把原来的第二个节点-next节点设置为头结点
 *         if (next == null)
 *             last = null;
 *         else
 *             next.prev = null; //next的头结点置空
 *         size--;
 *         modCount++;
 *         return element;
 *     }
[6]remove(Object o)、remove(index)
 *      public boolean remove(Object o) {
 *         if (o == null) { //若o=null
 *             for (Node<E> x = first; x != null; x = x.next) {//遍历节点,将所有item为null的节点全部删除
 *                 if (x.item == null) {
 *                     unlink(x);
 *                     return true;
 *                 }
 *             }
 *         } else {  //若o!=null,则遍历循环,删除所有item==o的节点
 *             for (Node<E> x = first; x != null; x = x.next) {
 *                 if (o.equals(x.item)) {
 *                     unlink(x);
 *                     return true;
 *                 }
 *             }
 *         }
 *
 *         return false;
 *     }
 *     public E remove(int index) {
 *         checkElementIndex(index);//检测下标是否越界
 *         return unlink(node(index));//执行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;
 *     }
[7]removeLast()
 *   public E removeLast() {
 *         final Node<E> l = last; //把last节点赋值给 l
 *         if (l == null)
 *             throw new NoSuchElementException();
 *         return unlinkLast(l);
 *     }
 *   private E unlinkLast(Node<E> l) {
 *         // assert l == last && l != null;
 *         final E element = l.item; //把尾节点的item赋值给element
 *         final Node<E> prev = l.prev; //把尾节点的前置节点赋值给prev
 *         l.item = null;
 *         l.prev = null; // 清空l节点
 *         last = prev; //把上个节点赋值给尾节点
 *         if (prev == null)
 *             first = null;
 *         else
 *             prev.next = null; //把上个节点的后置节点置空
 *         size--;
 *         modCount++;
 *         return element;
 *     }
[8]clear()
 *  public void clear() {
 *         //运用循环把所有的节点内容置空,头结点=尾节点=null,size=0
 *         for (Node<E> x = first; x != null; ) {
 *             Node<E> next = x.next;
 *             x.item = null;
 *             x.next = null;
 *             x.prev = null;
 *             x = next;
 *         }
 *         first = last = null;
 *         size = 0;
 *         modCount++;
 *     }

四、Vector和ArrayList的区别

类别VectorArrayList
JDK的引入版本1.01.2
初始化容量100
容量初始化的时机创建构造方法时调用add方法时
容量增长1倍0.5倍
是否采用了线程安全
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值