[集合]AbstractList源码解析(5.1)

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-11 17:30:05

AbstractList是List的一个实现类,并且继承了AbstractCollection。

开发者可以实现该接口,进行扩展集合。
如果要实现不可修改的list,需要实现get和size方法;
如果要实现可修改的list,必须额外实现set方法,如果集合的大小也可以改变,还需要实现add和remove方法。

接下来对于一些重要方法进行讲解

add(E e)

添加元素到集合的末尾

public boolean add(E e) {
    add(size(), e);
    return true;
}
public void add(int index, E element) {
    throw new UnsupportedOperationException();
}
public abstract int size();

add(E e)方法调用了add(int index, E element)和size,通过这可以知道如果这一方法没有被覆写,则直接抛出异常.因为add(size(),ze)这个add方法抛异常。另外,该方法调用了size方法,必须实现size方法

set(int index, E element)

在index位置设置元素element,覆盖原来的元素

public E set(int index, E element) {
    throw new UnsupportedOperationException();
}

看到这个抛出异常,你就知道如果你要调用该方法需要怎么做了吧
其他抛出异常的方法,也是如此,如果要调用,必须实现了

indexOf(Object o)

该接口是List的接口,在这里进行了一个默认实现,下面来瞅瞅

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,如果当前集合不包含此元素,返回-1,否则返回查找的第一个元素的索引位置
这里使用了一个莫有讲过的新接口,ListIterator,后面我们再来看看该接口到底说了啥

lastIndexOf(Object o)

使用迭代器,从后往前找元素,没找到返回-1,找到返回元素索引位置

public int lastIndexOf(Object o) {
    //从size()这个位置构建迭代器
    ListIterator<E> it = listIterator(size());
    if (o==null) {
        //hasPrevious 反向遍历列表,向前查找
        while (it.hasPrevious())
            //previous 列表中的上一个元素
            if (it.previous()==null)
                return it.nextIndex();
    } else {
        while (it.hasPrevious())
            if (o.equals(it.previous()))
                return it.nextIndex();
    }
    return -1;
}

clear()

调用了removeRange(int fromIndex, int toIndex)方法

/**
 * 清空集合
 */
public void clear() {
    removeRange(0, size());
}

removeRange(int fromIndex, int toIndex)

删除区间元素

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();
    }
}

利用ListIterator,遍历集合移除

addAll(int index, Collection<? extends E> c)

在从索引位置开始,依次加入集合c的元素

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;
}
/**
 * 越界判断,下标检查
 * @param index
 */
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();
}

这里没用迭代器,使用了增强for循环遍历元素,将c集合的元素一个一个加入到当前集合的指定位置中。
使用该方法也是需要重写add方法的

7个接口了,今天就到这里啦,下篇再见

AbstractList源码解析地址

https://github.com/chenhaoxiang/JDK1.8/blob/master/jdk-analyze/src/main/java/java/util/AbstractList.java

小手点点,实时收获源码解析,感谢您的star

下集预告:

AbstractList接口源码的继续讲解

插播广告:

未关注的贝贝可以来波关注啦。后续更多精彩内容等着您。
程序编程之旅

吾非大神,与汝俱进

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!