List集合

List集合

List集合框架

 *    |----Collection接口:单列集合,用来存储一个一个的对象
 *          |----List接口:存储有序的、可重复的数据。  -->“动态”数组,替换原有的数组
 *              |----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
 *              |----LinkedList:线程不安全对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
 *              |----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储

List接口当中的常用api方法

//除了Collection接口中的方法,还增加了一些根据元素索引来操作集合的特定方法
void add(int index,E element); 指定的元素添加到集合中的指定位置
boolean addAll​(int index, Collection<? extends E> c) 将指定集合中的所有元素插入到此列表中的指定位置(可选操作)。  
E get(int index); 根据指定的索引获取对应位置上的元素
int indexOf​(Object o) 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。  
int lastIndexOf​(Object o) 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。  
E remove(int index); 通过索引删除对位置上的元素
E set(int index ,E element); 在指定的位置上替换成给定的元素,并且放回
default void sort​(Comparator<? super E> c) 根据指定的Comparator引发的顺序排列此列表。    
List<E> subList​(int fromIndex, int toIndex) 返回指定的 fromIndex (含)和 toIndex之间的列表部分的视图。  

注意事项

  1. List接口中带索引的方法(特有的)
  2. 操作带索引的方法的时候,一定要防止索引越界异常
  3. foreach循环迭代数组/集合元素时,不能改变数组/集合元素的值,因此,不要对foreach的循环变量进行赋值
  4. foreach可以改变对象的值,但不能删除或添加对象.

list集合特点

  1. 有序,存储和取出元素顺序一致
  2. 可重复:存储的元素可以重复
  3. 元素以线性方式存储

Arraylist

  • java.util 包下下的
    底层是Object数组实现的,特点是查询速度快,增加删除慢
    jdk1.8 时,使用无参创建对象是默认容量时 10,长度不够时,自动增长0.5倍,就是原来数组的 .15倍

ArrayList的源码分析

  • jdk 7情况下

     *      ArrayList list = new ArrayList();//底层创建了长度是 10的Object[]数组elementData
     *      list.add(123);//elementData[0] = new Integer(123);
     *      ...
     *      list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
     *      默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
     *
    

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

  • jdk 8中ArrayList的变化:

     *      ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没有创建长度为10的数组
     *
     *      list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
     *      ...
     *      后续的添加和扩容操作与jdk 7 无异。
    

LinkedList集合

  • java.util.LinkedList 集合数据存储采用的是链表结构。方便元素的添加和删除操作

  • LinkedList是一个双向链表,特点,增删块,查询慢,在LinkedList集合当中,封装了大量关于首节点和尾节点的元素操作方法(开发中常用)

    public void addFirst(E e);将指定的元素插入到首节点位置
    public void addLast(E e); 将指定的元素插入到尾节点的位置上
    public E gerFirst(); 获取首节点元素
    public E getLast(); 获取尾节点元素
    public E removeFirst();	删除首节点的元素
    public E removeLast();	删除尾节点元素
    public E pop(); 从链表结构堆栈中弹出一个元素(首节点)
    public void push(E e); 将元素推入到此列表所表示的堆栈当中(首节点)
    public boolean isEmpty(); 如果此列表不包含任何元素,则返回true
    

LinkedList的源码分析:

 *      LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
 *      list.add(123);//将123封装到Node中,创建了Node对象。
 *
 *      其中,Node定义为:体现了LinkedList的双向链表的说法
 *      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;
             }
         }

LinkedList集合的特点

  1. 底层是一个链表结构,查询慢,增删快
  2. 里面包含了大量的首位节点操作的方法
  3. 允许所有的元素(包括null)
  4. 此实现不是同步的。如果多个线程同时访问一个连接表,而其中至少一个线程从结构上修改了该列表,则必须保持外部同步
  5. 元素有序的。

Vector的源码分析

  • *       jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。
    *       在扩容方面,默认扩容为原来的数组长度的2倍。
    

面试题:ArrayList、LinkedList、Vector三者的异同?

 *  同:三个类都是实现了List接口,存储数据的特点相同:存储有序的、可重复的数据
 *  不同:见上