上一篇文章,主要大致了解了了一下容器的类库,好了,废话不都说。
顺便提一句,我的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类根据在方法中创建一个匿名内部类,来实现自己的迭代方法。
好了,不说了,写到后面已经完全没有心情了,所以偷个懒。
文章中,有一些东西,借鉴了一些大牛的思想,毕竟,我也是一个小白。
如果文章中,有错误,告诉我,我会改正的,哈哈!