上一篇文章,主要大致了解了了一下容器的类库,好了,废话不都说。
顺便提一句,我的jdk是-1.8版本的,查看源码的时候,最好依照java api。
了解List,Set集合,首先需要看一下Collection。不多讲。
/*
Collection接口继承了Iterable,Iterable是一个迭代器,有三个方法,iterator(),forEach(Consumer super T> action),spliterator()
以前版本是Iterator迭代器,这里不多讲迭代器。
这里的Collection是一个接口,所以,成员和方法的修饰符都是public的
*/
public interface Collection extends Iterable {
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator iterator();
Object[] toArray();
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 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 spliterator() {
return Spliterators.spliterator(this, 0);
}
default Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
然后是AbstractCollection类,
/*
从代码上我们可以看到,AbstractCollection是一个抽象类,并且实现了Collection,
*/
public abstract class AbstractCollection implements Collection {
/*
这个构造方法的修饰符是protected,就是只能这个类虽在的包和子类可以创建实例
*/
protected AbstractCollection() {
}
/*
只有两个构造方法,iterator(),size(),所以子类必须实现这两个方法
*/
public abstract Iterator iterator();
public abstract int size();
public boolean isEmpty() {
return size() == 0;
}
public boolean contains(Object o) {
Iterator 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 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[] toArray(T[] a) {
int size = size();
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);//类型不确定,根据传入的类型,经过反射,得到该类的类型,并创建一个数组
Iterator 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[] 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 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 it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
//如果集合c中不包含集合中的元素,则删除
it.remove();
modified = true;
}
}
return modified;
}
public void clear() {
Iterator it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}
public String toString() {
Iterator 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 extends Collection {
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator iterator();
Object[] toArray();
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 operator) {
Objects.requireNonNull(operator);
final ListIterator 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 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 listIterator();
ListIterator listIterator(int index);
List subList(int fromIndex, int toIndex);
default Spliterator 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 iterator() {
return new Itr();
}
这个方法中返回一个Itr的对象,点进去,会发现Itr实现了Iterator,向下查看,下面还有一个Lisitr类,它继承了Itr,最终也是实现了Iterator。这两个类均实现了Iterator。也就是说AbstractList自己实现了迭代器,不需要我们在去实现了。下面我们看一下这两个类。
private class Itr implements Iterator {
int cursor = 0;//游标
int lastRet = -1;//上一次迭代到的元素的位置,每次使用完就会置为 -1
int expectedModCount = modCount;//用来判断是否发生并发操作的标示,如果这两个值不一致,就会报错,因为
//modCount记录的就是操作集合的次数,在多线程并发时,会出现值不一致的情况
public boolean hasNext() { return cursor != size();//仅仅是判断游标位置是否等于size()
/*
这个类,其实就是一个高配版的Itr类,因为Itr只有删除操作,而这个类有修改和添加操作,并且继承了Itr类,也有了删除操作
*/
private class ListItr extends Itr implements ListIterator {
/*
构造方法,创建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 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 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 it = listIterator(fromIndex);//循环遍历,进行删除
for (int i=0, n=toIndex-fromIndex; i
public boolean equals(Object o) {
/*
equals方法,几乎都是这样实现的,
第一步判断传入的对象是否就是该对象,如果相等,直接返回true
第二步,判断传入的对象的类型是否是List
第三步,就是遍历两个集合,。判断每个元素是否相等
*/
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator 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 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 extends SubList implements RandomAccess {
RandomAccessSubList(AbstractList list, int fromIndex, int toIndex) {
//构造方法也是调用了父类的构造方法
super(list, fromIndex, toIndex);
}
public List subList(int fromIndex, int toIndex) {
//这个方法,返回值是一个自己类的一个对象
return new RandomAccessSubList<>(this, fromIndex, toIndex);
}
截取方法,为什么要分为两个类呢?我们根据RandomAccess单词的字面量得知,随机访问。也就是说,实现了RandomAccess的类,是否支持随机访问,如果支持,遍历时会使用get(int index)方法,进行访问,不必要使用迭代器,因为迭代器的效率与之相比,较低。
接下来,我们看一下SubList类的源代码。算了,这里我就不就显示代码了,感觉这一篇代码量有点多,虽然只是粘贴复制,自己在IDEA上看吧,我简单介绍一下。
SubList类继承了AbstractList类,SubList并没有什么特殊的方法,方法内部还是调用的父类的方法。SubList类根据在方法中创建一个匿名内部类,来实现自己的迭代方法。
好了,不说了,写到后面已经完全没有心情了,所以偷个懒。
文章中,有一些东西,借鉴了一些大牛的思想,毕竟,我也是一个小白。
如果文章中,有错误,告诉我,我会改正的,哈哈!