Java集合学习三 AbstractList

一 AbstractList类的继承关系

可以看到这里有一个类是它本身的类,第二个类和第三个都是他的子类:SubList 和RandomAccessSubList,慢慢看。

二 AbstractList类本身的继承结构

可以看到它内部实现了除了实现了List接口的方法和继承实现了抽象Collection的方法外,内部还实现了两个迭代器:Itr 和 ListItr。

此外他还有一个关键的变量 

modCount :它的释义是:集合被改变的次数。如果该值发生意外的改变则会抛出ConcurrentModificationException并发修改异常当然是在next remove previous set add 方法中。当然这个字段对于子类来说是可选的,可以忽略。

三 先看下其中最下面新增的几个方法:

删除指定区间的元素,通过迭代器遍历
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();
        }
    }

索引判断
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();
    }

 

四  实现自list接口的方法和AbstractCollection的方法

set ,add,remove 操作都是默认抛出不支持操作异常的方法。

查找元素索引值,可以为空,所以判断。
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;
    }

查找元素最后一次出现的索引值,可以为空,所以判断。

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());
    }
通过指定索引值插入集合中的所有元素,遍历插入。
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;
    }

 

 五 再来看看内部类里面的的Itr迭代器类

可以看到有三个变量,一个一个看。

cursor :元素的索引,将由后续调用next返回。

lastRet:最近一个调用next 和 previous 保存下来的索引值,若元素删除,则重置为0

expectedModCount:

返回当前游标是不是达到集合元素的最大值

public boolean hasNext() {
            return cursor != size();
        }
返回迭代器指向的下一个元素
public E next() {
            checkForComodification();
            try {
                int i = cursor; //当前游标索引值
                E next = get(i);//得到元素
                lastRet = i;//保存最近一次next的索引值
                cursor = i + 1;//游标++
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }
迭代器提供了删除方法,删除自上一个next 或 pervious 保存的索引值,
public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;将游标退回
                lastRet = -1;重置为-1
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }
判断当前是不是有多个线程在修改,是的话,抛出并行操作异常
final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

 

 六 ListItr

该类在继承了Itr的基础上还实现了ListIterator的方法

主要是多了前后遍历访问的功能,线性表。

七 看完了内部类,再看下另外两个子类 先看SubList

该类可以截取集合中的元素返回一个他的子类,实际根本就没有返回新集合,还是原来的集合,根据构造函数fromIndex,toIndex设置了偏移量offset=fromIndex,和size=toIndex-fromIndex。每次还是操作的原集合,只不过加了一个偏移量offset。

 

有三个变量:

class SubList<E> extends AbstractList<E> {
    private final AbstractList<E> l;  传入的集合类
    private final int offset;          偏移量
    private int size;                  截取的元素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 +
                                               ") > toIndex(" + toIndex + ")");
        l = list;
        offset = fromIndex;
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }

    public E set(int index, E element) {
        rangeCheck(index);
        checkForComodification();
        return l.set(index+offset, element);
    }

    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return l.get(index+offset);
    }

    public int size() {
        checkForComodification();
        return size;
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);
        checkForComodification();
        l.add(index+offset, element);
        this.modCount = l.modCount;
        size++;
    }

    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = l.remove(index+offset);
        this.modCount = l.modCount;
        size--;
        return result;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        l.removeRange(fromIndex+offset, toIndex+offset);
        this.modCount = l.modCount;
        size -= (toIndex-fromIndex);
    }

    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        int cSize = c.size();
        if (cSize==0)
            return false;

        checkForComodification();
        l.addAll(offset+index, c);
        this.modCount = l.modCount;
        size += cSize;
        return true;
    }

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

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

        return new ListIterator<E>() {
            private final ListIterator<E> i = l.listIterator(index+offset);

            public boolean hasNext() {
                return nextIndex() < size;
            }

            public E next() {
                if (hasNext())
                    return i.next();
                else
                    throw new NoSuchElementException();
            }

            public boolean hasPrevious() {
                return previousIndex() >= 0;
            }

            public E previous() {
                if (hasPrevious())
                    return i.previous();
                else
                    throw new NoSuchElementException();
            }

            public int nextIndex() {
                return i.nextIndex() - offset;
            }

            public int previousIndex() {
                return i.previousIndex() - offset;
            }

            public void remove() {
                i.remove();
                SubList.this.modCount = l.modCount;
                size--;
            }

            public void set(E e) {
                i.set(e);
            }

            public void add(E e) {
                i.add(e);
                SubList.this.modCount = l.modCount;
                size++;
            }
        };
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new SubList<>(this, fromIndex, toIndex); //这里返回的对象还是传入的集合类本身
    }

    //索引判断是否越界
    private void rangeCheck(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(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;
    }

    private void checkForComodification() {
        if (this.modCount != l.modCount)
            throw new ConcurrentModificationException();
    }
}

 

八 最后看下RandomAccessSubList

这玩意就是继承自面SubList并且实现了RandomAccess随机访问接口的实现类。

class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
        super(list, fromIndex, toIndex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new RandomAccessSubList<>(this, fromIndex, toIndex);
    }
}

总结:SubList 那里应该注意下,返回的截取后的list还是传入时的list,如果add等等操作后,原来的list也会变化。

还要了解下RandomAccess接口啊。看了一篇文章,大概了解了这个接口的作用。标记接口,通常做判断用,然后根据判断是狗实现RandomAccess接口,在调用高效的算法进行处理访问。https://blog.youkuaiyun.com/ted_cs/article/details/82852093连接在这!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值