jdk源码——集合(一)

上一篇文章,主要大致了解了了一下容器的类库,好了,废话不都说。

顺便提一句,我的jdk是-1.8版本的,查看源码的时候,最好依照java api。


了解List,Set集合,首先需要看一下Collection。不多讲。

 
 
/*
Collection接口继承了Iterable,Iterable是一个迭代器,有三个方法,iterator(),forEach(Consumer<? super T> action),spliterator()
以前版本是Iterator迭代器,这里不多讲迭代器。
这里的Collection是一个接口,所以,成员和方法的修饰符都是public的
 */
public interface Collection<E> extends Iterable<E> {
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean add(E e);
    boolean remove(Object o);
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    boolean removeAll(Collection<?> c);
    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }
    boolean retainAll(Collection<?> c);
    void clear();
    boolean equals(Object o);
    int hashCode();
    @Override
    /*
    这个方法是重写,因为父类Iterable包含该 方法
     */
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}


然后是AbstractCollection类,

 
/*
从代码上我们可以看到,AbstractCollection是一个抽象类,并且实现了Collection,
 */
public abstract class AbstractCollection<E> implements Collection<E> {

    /*
    这个构造方法的修饰符是protected,就是只能这个类虽在的包和子类可以创建实例
     */
    protected AbstractCollection() {
    }
    /*
    只有两个构造方法,iterator(),size(),所以子类必须实现这两个方法
     */
    public abstract Iterator<E> iterator();
    public abstract int size();
    public boolean isEmpty() {
        return size() == 0;
    }
    public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    //传入的null,会与遍历得到的元素进行比较
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }
    public Object[] toArray() {
        Object[] r = new Object[size()];//创建一个Object数组
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++) {
            /*
            迭代器数量小于size,为什么会出现这样的情况呢?如ArrayList,底层是一个数组,指定了大小,但是并未有实际值,就会出现
            迭代器数量小于size的情况
             */
            if (! it.hasNext())
                //下一个值不存在
                return Arrays.copyOf(r, i);//复制元素(这里实际上截取元素),返回返回一个长度为i的新数组,
            r[i] = it.next();//实际上的赋值操作
        }
        //当迭代器数量大于size时,使用finishToArray(),此时的r,已经是一个长度为size的数组,并且每个元素都有具体的值
        return it.hasNext() ? finishToArray(r, it) : r;
    }
    /*
    这个方法和toArrray()思路一致,这两个方法是重载方法
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        int size = size();
        T[] r = a.length >= size ? a :
                  (T[])java.lang.reflect.Array
                  .newInstance(a.getClass().getComponentType(), size);//类型不确定,根据传入的类型,经过反射,得到该类的类型,并创建一个数组
        Iterator<E> it = iterator();

        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) {
                if (a == r) {
                    r[i] = null; // null-terminate
                } else if (a.length < i) {
                    return Arrays.copyOf(r, i);
                } else {
                    System.arraycopy(r, 0, a, 0, i);
                    if (a.length > i) {
                        a[i] = null;
                    }
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        return it.hasNext() ? finishToArray(r, it) : r;
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//设置Array的最大长度
    @SuppressWarnings("unchecked")
    private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
        int i = r.length;//迭代器当前长度
        while (it.hasNext()) {
            int cap = r.length;//cap表示当前数组的大小
            if (i == cap) {
                //此时,迭代器当前长度==数组的长度是,需要扩容
                int newCap = cap + (cap >> 1) + 1;//扩容后数组的长度,长度为原来的一倍+1
                // overflow-conscious code
                if (newCap - MAX_ARRAY_SIZE > 0)
                    //如果长度已经超过了(2147483647-8),就不能继续按照原来的方法扩容,
                    newCap = hugeCapacity(cap + 1);//
                r = Arrays.copyOf(r, newCap);
            }
            r[i++] = (T)it.next();//因为迭代器长度超过数组长度,要继续想数组中添加元素
        }
        return (i == r.length) ? r : Arrays.copyOf(r, i);
    }
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) //如果最小长度小于0,会抛出异常
            throw new OutOfMemoryError
                ("Required array size too large");
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;//如果minCapacity>MAX_ARRAY_SIZE,则返回MAX_VALUE
    }
    public boolean add(E e) {
        //不能进行添加,会抛出异常
        throw new UnsupportedOperationException();
    }
    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext()) {
                if (it.next()==null) {
                    it.remove();
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (o.equals(it.next())) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }
    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }

    /*
    删除的不是c集合
     */
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);//会判断该集合是否为null
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }
    /*
    仅保留此 collection 中那些也包含在指定 collection 的元素
     */
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                //如果集合c中不包含集合中的元素,则删除
                it.remove();
                modified = true;
            }
        }
        return modified;
    }
    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
    }
    }
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";
        StringBuilder sb = new StringBuilder();//使用的是StringBuilder,是可以改变的,因为String是不可变的
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

}


         AbstractCollection类是无法进行添加操作的,因为add()方法内部会抛出一个异常,所以addAll()方法也就无法使用了。所以继承的子类,如果有添加数据的操作时,必须实现add()方法

     接下来,就是list接口了,

/*
List接口继承了Collection
 */
public interface List<E> extends Collection<E> {

    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean add(E e);
    boolean remove(Object o);
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    boolean addAll(int index, Collection<? extends E> c);
    boolean removeAll(Collection<?> c);
    boolean retainAll(Collection<?> 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()));
        }
    }
    @SuppressWarnings({"unchecked", "rawtypes"})
    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);
        }
    }
    void clear();
    boolean equals(Object o);
    int hashCode();
    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<E> subList(int fromIndex, int toIndex);
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.ORDERED);
    }
}

       感觉没有什么好说的,只有一处,我在看是有一点疑惑,就是List是一个接口,为什么有三个方法会有方法体?

       :我们可以比较出,这三个方法前有一个default关键字,这个关键字是java8的新特新,可以使得接口中的方法有方法体,被该关键字修饰的方法,其子类不必去实现该方法,如果实现了该方法,和重写一般,符合java多态。


         下面就是AbstractList了,先看一下该类的类结构图:


  先看一下集合最常用的添加,修改,删除,获取方法:

   public boolean add(E e) {
        add(size(), e);//调用了父类中的size()方法,该方法是一个抽象方法,没有实现
        return true;
    }

    abstract public E get(int index);//是一个抽象方法

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

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

    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

这几个方法,都无法使用,因内部都是抛出异常


AbstractList继承了AbstRactCollection,所以查看一下这两个方法size()和itearator()方法。AbstractList实现了iterator(),但是依旧没有实现size()。

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

     这个方法中返回一个Itr的对象,点进去,会发现Itr实现了Iterator,向下查看,下面还有一个Lisitr类,它继承了Itr,最终也是实现了Iterator。这两个类均实现了Iterator。也就是说AbstractList自己实现了迭代器,不需要我们在去实现了。下面我们看一下这两个类。

private class Itr implements Iterator<E> {

        int cursor = 0;//游标

        int lastRet = -1;//上一次迭代到的元素的位置,每次使用完就会置为 -1

      int expectedModCount = modCount;//用来判断是否发生并发操作的标示,如果这两个值不一致,就会报错,因为
                                      //modCount记录的就是操作集合的次数,在多线程并发时,会出现值不一致的情况 
public boolean hasNext() { return cursor != size();//仅仅是判断游标位置是否等于size()
  } public E next() { checkForComodification(); try { int i = cursor; E next = get(i);//游标0位置开始获取元素 lastRet = i;//记录本次操作 cursor = i + 1;//游标后移一位 return next;//返回本次操作所得到的元素 } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet < 0) //上一次操作的游标位置,小于0,证明没有调用next(),所以无法删除 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(); } }
    /*
    这个类,其实就是一个高配版的Itr类,因为Itr只有删除操作,而这个类有修改和添加操作,并且继承了Itr类,也有了删除操作
     */
    private class ListItr extends Itr implements ListIterator<E> {
        /*
        构造方法,创建LitItr时,指定了一个int类型的数,作用是直接指定游标所在的位置
         */
        ListItr(int index) {
            cursor = index;
        }

        /*
         前面是否有元素,除了第一个元素之外,其他元素前面都有
         */
        public boolean hasPrevious() {
            return cursor != 0;//只需要判断cursor是否等于0即可
        }

        /*
        获取游标前一位的元素
         */
        public E previous() {
            checkForComodification();
            try {
                int i = cursor - 1;//将游标位置前移
                E previous = get(i);//获得该元素
                lastRet = cursor = i;//记录上次操作的位置,并将cursor设置文现在游标所在的位置
                return previous;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        /*
        返回的是下一次游标所在的位置
         */
        public int nextIndex() {
            return cursor;
        }

        /*
        返回的是上一次游标所在的位置
         */
        public int previousIndex() {
            return cursor-1;
        }
        /*
        替换值,因为set()内部只是抛出一个异常
         */
        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();
            }
        }

        /*
       替换值,因为add()内部只是抛出一个异常
        */
        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();
            }
        }
    }

    然后,我们再看一下AbstractList的其他方法。

     /*
    返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1
     */
    public int indexOf(Object o) {
        ListIterator<E> it = listIterator();//使用的是高配版的迭代器
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)//next(),游标位置已经后移了,所以要返回本次操作的位置,必须再次前移
                    return it.previousIndex();
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return it.previousIndex();
        }
        return -1;
    }

    /*
    返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -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) {//foreach进行添加
            add(index++, e);
            modified = true;
        }
        return modified;
    }
    /*
   clean进行清除,实际调用的是这个方法,进行遍历删除
    */
    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();
        }
    }
    
public boolean equals(Object o) {
        /*
        equals方法,几乎都是这样实现的,
                第一步判断传入的对象是否就是该对象,如果相等,直接返回true
                第二步,判断传入的对象的类型是否是List
                第三步,就是遍历两个集合,。判断每个元素是否相等
         */
        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;
    }

     

      现在AbstractList类中,只有一个方法还没有讲解,就是subList(int formindex,int toindex)方法了,该方法的作用就是截取指定范围内的部分视图,[formindex,toindex)。

 

public List<E> subList(int fromIndex, int toIndex) {
        //判断这个对象的类型时不是RandomAccess类型的,如果是,则创建RandomAccessSubList的对象,不是,则创建SubList的对象
        return (this instanceof RandomAccess ?
                new RandomAccessSubList(this,fromIndex, toIndex) :
                new SubList<>(this, fromIndex, toIndex));

 }

      根据上面的subList(formindex,toindex)方法,得知内部创建了两个类的对象,这两个类还是AbstractList类的内部类,下图是这两个类的结构图:

我们先看一下RandomAccessSublist这个类,因为这个类的方法比较少,有简单的开始。

/*
这个RandomAccessSubList内部类,继承了SubList,实现了RandomAccess,我们会发现,SubList又继承AbstractList
点击RandomAccess时,会发现,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);
    }

      截取方法,为什么要分为两个类呢?我们根据RandomAccess单词的字面量得知,随机访问。也就是说,实现了RandomAccess的类,是否支持随机访问,如果支持,遍历时会使用get(int index)方法,进行访问,不必要使用迭代器,因为迭代器的效率与之相比,较低。


接下来,我们看一下SubList类的源代码。算了,这里我就不就显示代码了,感觉这一篇代码量有点多,虽然只是粘贴复制,自己在IDEA上看吧,我简单介绍一下。

     SubList类继承了AbstractList类,SubList并没有什么特殊的方法,方法内部还是调用的父类的方法。SubList类根据在方法中创建一个匿名内部类,来实现自己的迭代方法。

   好了,不说了,写到后面已经完全没有心情了,所以偷个懒。

  文章中,有一些东西,借鉴了一些大牛的思想,毕竟,我也是一个小白。

  如果文章中,有错误,告诉我,我会改正的,哈哈!

大笑大笑大笑大笑大笑



   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值