4、List接口详解

List简介

list:集合中的元素按照索引的位置排序,集合中的元素可以重复,可以为null,允许按照对象在集合中的索引位置检索对象,遍历的顺序和放入的顺序是一致的。

List接口的定义

List的定义如下:

public interface List<E> extends Collection<E> {
   //省略了Collection接口中已有的方法
/**
* 添加集合到指定的位置
*/
    boolean addAll(int index, Collection<? extends E> c);

    default void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final ListIterator<E> li = this.listIterator();
        while (li.hasNext()) {
            li.set(operator.apply(li.next()));
        }
    }
/**
* 排序
*/
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }


/**
* 获取指定位置的元素
*/
    E get(int index);
    /**
    * 设置指定位置的元素
*/

    E set(int index, E element);
/**
* 添加到指定的位置
*/
    void add(int index, E element);
/**
* 移除指定位置的元素
*/

    E remove(int index);
/**
* 第一次出现这个元素的位置
*/
    int indexOf(Object o);
    /**
    * 最后一次出现这个元素的位置
    */
    int lastIndexOf(Object o);

/**
*用于list 的迭代器
* 类似于标准的迭代器
*/
    ListIterator<E> listIterator();

    ListIterator<E> listIterator(int index);

  /**
   * 截取list
   */
    List<E> subList(int fromIndex, int toIndex);


    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.ORDERED);
    }

}

AbstractList

AbstractList 是一个抽象类,它继承于AbstractCollection。AbstractList实现List接口中除size()、get(int location)之外的函数。

public interface List<E> extends Collection<E> {
   //省略了Collection接口中已有的方法
/**
* 添加集合到指定的位置
*/
    boolean addAll(int index, Collection<? extends E> c);

    default void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final ListIterator<E> li = this.listIterator();
        while (li.hasNext()) {
            li.set(operator.apply(li.next()));
        }
    }
/**
* 排序
*/
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }


/**
* 获取指定位置的元素
*/
    E get(int index);
    /**
    * 设置指定位置的元素
*/

    E set(int index, E element);
/**
* 添加到指定的位置
*/
    void add(int index, E element);
/**
* 移除指定位置的元素
*/

    E remove(int index);
/**
* 第一次出现这个元素的位置
*/
    int indexOf(Object o);
    /**
    * 最后一次出现这个元素的位置
    */
    int lastIndexOf(Object o);

/**
* 类似于标准的迭代器
*/
    ListIterator<E> listIterator();

    ListIterator<E> listIterator(int index);

  /**
   * 截取list
   */
    List<E> subList(int fromIndex, int toIndex);


    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.ORDERED);
    }

}

List是一个继承于Collection的接口,即List是集合中的一种。List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允许有重复的元素。

上面的方法为list中特有的方法,上面的方法主要是位置相关的,因为list是带有下标的。

AbstractList

AbstractList 是一个抽象类,它继承于AbstractCollection。AbstractList实现List接口中除size()、get(int location)之外的函数。

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {

    protected AbstractList() {
    }


    //默认添加在最后的位置
    public boolean add(E e) {
        add(size(), e);
        return true;
    }
    /**
    * 修改指定位置的元素
* @param index
* @param element
*/
    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }

    /**
    * 添加到指定的位置
 */ 
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    //真正的list类实现
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

    /**
    * 获取指定位置的元素
*/
    abstract public E get(int index);


 /**返回第一次出现o的索引
 * 1、判断o是否是null
 * 2、true集合中是否有null的元素,如果有则返回迭代器的上一位置
 * 3、false 判断集合中是否有和o相等的元素,如果有则返回迭代器的上一位置
 * 4、如果没有相同的则返回-1.
*/
    public int indexOf(Object o) {
        ListIterator<E> it = listIterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return it.previousIndex();
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return it.previousIndex();
        }
        return -1;
    }

  /**
  * 返回最后o在集合中最后出现的位置
  * 此处是通过,listIterator的逆序来实现的
  */
    public int lastIndexOf(Object o) {
        ListIterator<E> it = listIterator(size());
        if (o==null) {
            while (it.hasPrevious())
                if (it.previous()==null)
                    return it.nextIndex();
        } else {
            while (it.hasPrevious())
                if (o.equals(it.previous()))
                    return it.nextIndex();
        }
        return -1;
    }



    public void clear() {
        removeRange(0, size());
    }
/**
* 在指定的索引位置开始放入集合,原来位置的元素依次顺移,
* index介于0和size之间
*/
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        boolean modified = false;
        for (E e : c) {
            add(index++, e);
            modified = true;
        }
        return modified;
    }



    public Iterator<E> iterator() {
        return new Itr();
    }


    public ListIterator<E> listIterator() {
        return listIterator(0);
    }


    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }

    private class Itr implements Iterator<E> {
      //具体实现稍后详细分析
    }

    private class ListItr extends Itr implements ListIterator<E> {
        //待详细分析
}
//该SubLsit是ArrayList的内部类,它与ArrayList一样,都是继承AbstractList和实现RandomAccess接口
class SubList<E> extends AbstractList<E> {
    private final AbstractList<E> l;
    private final int offset;
    private int size;
/**
* 
*/
    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > list.size())
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
        //l = list;而list就是在前面传递过来的list,也就是说l 就是原始list的引用。 
        // 同时在构造函数中它甚至将modCount(fail-fast机制)传递过来了                                     ") > toIndex(" + toIndex + ")");
        l = list;
        offset = fromIndex;
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }

 //其他方法的实现都是依赖AbstractList中的实现
}
//表明支持随机访问
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {

}

内部类Itr源码分析

    private class Itr implements Iterator<E> {
        /**
        *当前迭代器的位置,初始化的时候位于0索引的左边,调用next后位于索引0和1之间
        * cursor对于每次调用next方法就增加一次 
        */
        int cursor = 0;
/**
* 上一个cursor的值就等于lastRet(用于删除操作)每次跳过的元素的坐标
*/
        int lastRet = -1;
          /**
          * 迭代器在进行结构性的操作的时候expectedModCount加一
          */
        int expectedModCount = modCount;
        /**
        * 是否是最后一个元素
        * 1、比较cursor的值和size的大小。如果两者相等则说明迭代到尾了。
        */
        public boolean hasNext() {
            return cursor != size();
        }
        /**
        * 返回的是光标经过的上一个索引的元素
        * 1、检查集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过
        * 2、i = cursor 记录光标的位置
        * 3、 获取光标经过的元素
        * 4、lastRet = i 前一个元素对应的光标
        * 5、光标加1
        * 
        */
        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }
        /**
        * 一个remove之前必须要有一个next
        * 删除光标经过的的元素
        * 1、判断上一个光标的位置,有2中情况等于-1
        *   1、1 初始化的时候没有调用next方法,直接调用remove方法
        *   1.2 连续2次调用remove方法
        * 2、 调用ArrayList本身的remove()方法删除lastRet位置元素
        * 3、修改cursor和lastRet
        * 4、修改expectedModCount
        * 
        */
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

modCount在list、map、set中都有这个参数,这个参数的作用是记录修改的次数。

使用modCount属性的集合全是全是线程不安全的,

在一个迭代器初始的时候会赋予它调用这个迭代器的对象的mCount,如何在迭代器遍历的过程中,一旦发现这个对象的mcount和迭代器中存储的mcount不一样那就抛异常
就是fail-fast

内部类ListItr源码分析


private class ListItr extends Itr implements ListIterator<E> {

        ListItr(int index) {
            cursor = index;
        }

        /**
        * 如果以逆向遍历列表,列表迭代器前面还有元素,则返回 true,否则返回false
        * 根据cursor=0,为迭代器初始化的位置。
        */
        public boolean hasPrevious() {
            return cursor != 0;
        }
        /**
        * 返回游标左边的元素
        * 1、检查集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过
        * 2、i = cursor-1 记录光标左边元素的索引
        * 3、 根据索引获取,光标左边的元素
        * 4、 lastRet = cursor = i修改光标跳过的元素的索引
        */
        public E previous() {
            checkForComodification();
            try {
                int i = cursor - 1;
                E previous = get(i);
                lastRet = cursor = i;
                return previous;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }
        /**
        *返回调用next后所返回元素的索引
        */
        public int nextIndex() {
            return cursor;
        }
        /**
        * 返回调用previous后所返回元素的索引。
        */
        public int previousIndex() {
            return cursor-1;
        }
         /**
         * 用指定元素替换 next 或 previous 返回的元素
         * 1、判断光标经过的元素坐标是否为-1(迭代器初始化的时候,或者连续2次调用修改结构性的方法)
         * 2、 调用AbstractList的set
         * 3、修改expectedModCount
         */
        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.set(lastRet, e);
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
        /**
        * 将指定的元素插入列表
        * 1、检查集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过
        * 2、将元素插入到光标的后边
        * 3、发生了结构性的修改,lastRet重置为-1
        * 4、将光标向右移动一位
        * 5、 修改expectModCount
        */
        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                AbstractList.this.add(i, e);
                lastRet = -1;
                cursor = i + 1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return (this instanceof RandomAccess ?
                new RandomAccessSubList<>(this, fromIndex, toIndex) :
                new SubList<>(this, fromIndex, toIndex));
    }

    // Comparison and hashing

     /**
     * 比较两个集合是否相同
    */
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof List))
            return false;

        ListIterator<E> e1 = listIterator();
        ListIterator<?> e2 = ((List<?>) o).listIterator();
        while (e1.hasNext() && e2.hasNext()) {
            E o1 = e1.next();
            Object o2 = e2.next();
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }
        return !(e1.hasNext() || e2.hasNext());
    }

    public int hashCode() {
        int hashCode = 1;
        for (E e : this)
            hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
        return hashCode;
    }


    protected void removeRange(int fromIndex, int toIndex) {
        ListIterator<E> it = listIterator(fromIndex);
        for (int i=0, n=toIndex-fromIndex; i<n; i++) {
            it.next();
            it.remove();
        }
    }


    protected transient int modCount = 0;

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size())
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size();
    }
}

ListItr实现了ListIterator接口同时继承了Itr,此接口是Iterator接口的扩展,使迭代器不但可以向后遍历,也可以向前遍历,还可以获取将要遍历元素的下标,
和当前元素的下标,同时可以通过迭代器对元素进行添加、删除、修改的操作

SubList

//该SubLsit是ArrayList的内部类,它与ArrayList一样,都是继承AbstractList和实现RandomAccess接口
class SubList<E> extends AbstractList<E> {
    private final AbstractList<E> l;
    private final int offset;
    private int size;
/**
* 
*/
    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > list.size())
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
        //l = list;而list就是在前面传递过来的list,也就是说l 就是原始list的引用。 
        // 同时在构造函数中它甚至将modCount(fail-fast机制)传递过来了                                     ") > toIndex(" + toIndex + ")");
        l = list;
        offset = fromIndex;
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }

 //其他方法的实现都是依赖AbstractList中的实现
}

它返回原来list的从[fromIndex, toIndex)之间这一部分的视图,之所以说是视图,是因为实际上,返回的list是靠原来的list支持的。

如果发生结构性修改的是返回的子list,那么原来的list的大小也会发生变化;

而如果发生结构性修改的是原来的list(不包括由于返回的子list导致的改变),那么返回的子list语义上将会是undefined。在AbstractList(ArrayList的父类)中,undefined的具体表现形式是抛出一个ConcurrentModificationException。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值