Java集合框架-AbstractCollection Java集合框架具体实现关系
由点组成的方框 如 表示接口
由小段线组成的方框 如 表示抽象类
由实线组成的方框 如 表示实体类
AbstractCollection AbstractCollection是一个抽象类 ,最大限度地实现了Collection接口的方法(抽象类不必实现接口类的所有方法) ,仅剩下size()和iterator()方法在适当的子类实现
默认的AbstractCollection的实现类是一个不可修改(添加元素) 的集合,只需要
实现size()和iterator()方法
实现返回的迭代器中的hasNext()和next()方法
若需要AbstractCollection的实现类是一个可修改(添加元素) 的集合,则需要
重写覆盖add()方法 (AbstractCollection的add()方法默认抛出 UnsupportedOperationException
异常)
实现返回的迭代器中的remove()方法 (Iterator接口的remove()方法默认抛出UnsupportedOperationException
异常)
AbstractCollection实现源码分析 1.源码整体架构 构造函数+抽象方法
1 2 3 4 5 6 7 8 9 10 11 public abstract class AbstractCollection <E > implements Collection <E > { protected AbstractCollection () { } public abstract int size () ; public abstract Iterator<E> iterator () ; }
2.add(E e):boolean 1 2 3 4 5 public boolean add (E e) { throw new UnsupportedOperationException(); }
3.遍历集合元素的实现方法 contains、remove都是采取遍历集合元素根据传入参数是否为null来进行不同的比较方法 的实现方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 public boolean contains (Object o) { Iterator<E> it = iterator(); if (o==null ) { while (it.hasNext()) if (it.next()==null ) return true ; } else { while (it.hasNext()) if (o.equals(it.next())) return true ; } return false ; } public boolean containsAll (Collection<?> c) { for (Object e : c) if (!contains(e)) return false ; return true ; } 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 removeAll (Collection<?> c) { Objects.requireNonNull(c); boolean modified = false ; Iterator<?> it = iterator(); while (it.hasNext()) { if (c.contains(it.next())) { it.remove(); modified = true ; } } return modified; } public boolean addAll (Collection<? extends E> c) { boolean modified = false ; for (E e : c) if (add(e)) modified = true ; return modified; } public boolean retainAll (Collection<?> c) { Objects.requireNonNull(c); boolean modified = false ; Iterator<E> it = iterator(); while (it.hasNext()) { if (!c.contains(it.next())) { it.remove(); modified = true ; } } return modified; }
4.toArray():Object[] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 public Object[] toArray() { Object[] r = new Object[size()]; Iterator<E> it = iterator(); for (int i = 0 ; i < r.length; i++) { if (! it.hasNext()) return Arrays.copyOf(r, i); r[i] = it.next(); } return it.hasNext() ? finishToArray(r, it) : r; } private static <T> T[] finishToArray(T[] r, Iterator<?> it) { int i = r.length; while (it.hasNext()) { int cap = r.length; if (i == cap) { int newCap = cap + (cap >> 1 ) + 1 ; if (newCap - MAX_ARRAY_SIZE > 0 ) 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 ) throw new OutOfMemoryError ("Required array size too large" ); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
5.toArray(T[] a): T[] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 ; } 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; }
6.toString():String 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public String toString () { Iterator<E> it = iterator(); if (! it.hasNext()) return "[]" ; StringBuilder sb = new StringBuilder(); sb.append('[' ); for (;;) { E e = it.next(); sb.append(e == this ? "(this Collection)" : e); if (! it.hasNext()) return sb.append(']' ).toString(); sb.append(',' ).append(' ' ); } }
AbstractSet 继承了AbstractCollection抽象类,AbstractSet抽象类没有覆盖AbstractCollection类中任何实现 ,它只是添加了equals(Object o)和hashCode实现
AbstractSet实现源码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 public abstract class AbstractSet <E > extends AbstractCollection <E > implements Set <E > { protected AbstractSet () { } public boolean equals (Object o) { if (o == this ) return true ; if (!(o instanceof Set)) return false ; Collection<?> c = (Collection<?>) o; if (c.size() != size()) return false ; try { return containsAll(c); } catch (ClassCastException unused) { return false ; } catch (NullPointerException unused) { return false ; } } public int hashCode () { int h = 0 ; Iterator<E> i = iterator(); while (i.hasNext()) { E obj = i.next(); if (obj != null ) h += obj.hashCode(); } return h; } public boolean removeAll (Collection<?> c) { Objects.requireNonNull(c); boolean modified = false ; if (size() > c.size()) { for (Iterator<?> i = c.iterator(); i.hasNext(); ) modified |= remove(i.next()); } else { for (Iterator<?> i = iterator(); i.hasNext(); ) { if (c.contains(i.next())) { i.remove(); modified = true ; } } } return modified; } }
equals()方法通过多重的判定 来提升效率,而不是直接进行集合各元素的比较
removeAll()方法通过比较集合元素数量和集合c元素数量, 遍历元素数量少的集合,提升效率
hashCode()方法通过所有元素都是Object对象的实例 ,调用Object类的hashCode()方法 得到所有元素的哈希码,我们来看下Object类的hashCode()方法研究下怎么计算单个元素的哈希码
1 2 3 public class Object { public native int hashCode () ; }
源码中Object类的hashCode()是采用native 修饰符修饰的方法,简单来说,native方法就是一个Java调用非Java代码的接口 ,称作JNI(Java Native Interface)Java本地接口 ,官方定义为
“A native method is a Java method whose implementation is provided by non-java code.”
如图是Java代码通过JNI接口调用C++代码的方式,JNI的书写步骤如下
编写带有native声明 的方法的Java类
使用javac 命令编译编写的Java类
使用java -jni 来生成后缀名为.h的头文件
使用其他语言(C、C++)实现本地方法
将本地方法编写的文件生成动态链接库(DLL)
AbstractList AbstractList主要用于最大程度实现随机访问 数据(数组)的接口,对于顺序访问数据(链表)的类应该优先使用AbstractSequentialList类
AbstractList继承AbstractCollection抽象类 ,AbstractCollection要求子类需要实现size()和iterator()方法 ,AbstractList仅实现了iterator()方法
AbstractList实现了List接口 ,实现了其中的一些方法,新增了一个抽象方法get(int)
AbstractList的继承类要实现不可修改元素的列表 ,只需要实现get(int)【From List】和size()方法【From AbstractCollection】
AbstractList的继承类要实现可修改元素的列表 ,还要重写add(),set(),remove()方法,否则会抛出UnsupportedOperationException
异常
源码分析 1.默认不支持的方法 需要继承类根据自身特点实现或者重写的方法
抽象方法:get(int)
从AbstractCollection继承的方法:add(E)
从List接口实现的不支持的方法:add(int,E),set(int,E),remove(int)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 abstract public E get (int index) ;public boolean add (E e) { add(size(), e); return true ; } public void add (int index, E element) { throw new UnsupportedOperationException(); } public E set (int index, E element) { throw new UnsupportedOperationException(); } public E remove (int index) { throw new UnsupportedOperationException(); }
2.实现的iterator()方法和Itr内部类 实现了从AbstractCollection继承的iterator()方法 ,实现了Iterator接口 ,实现了迭代器的基础功能,为ListItr提供基础方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public Iterator<E> iterator () { return new Itr(); } protected transient int modCount = 0 ;private class Itr implements Iterator <E > { int cursor = 0 ; int lastRet = -1 ; int expectedModCount = modCount; final void checkForComodification () { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } public boolean hasNext () { return cursor != size(); } public E next () { checkForComodification(); try { int i = cursor; E next = get(i); lastRet = i; cursor = i + 1 ; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove () { if (lastRet < 0 ) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this .remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1 ; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } }
3.实现的listIterator()方法和ListItr内部类 通过ListItr内部类 实现了List接口的listIterator和listIterator(int index)方法 ,其余的List接口的方法的实现都是基于ListItr列表迭代器 实现
ListItr内部类主要通过继承Itr实现的方法 来实现列表迭代器功能 ,相比于Itr增加了向前遍历、设置cursor游标位置 等功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 public ListIterator<E> listIterator () { return listIterator(0 ); } public ListIterator<E> listIterator (final int index) { rangeCheckForAdd(index); return new ListItr(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 class ListItr extends Itr implements ListIterator <E > { ListItr(int index) { cursor = index; } public boolean hasPrevious () { return cursor != 0 ; } public E previous () { checkForComodification(); try { int i = cursor - 1 ; E previous = get(i); lastRet = cursor = i; return previous; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public int nextIndex () { return cursor; } public int previousIndex () { return cursor-1 ; } 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(); } } 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(); } } }
4.基于ListItr实现或者重写的方法
基于ListItr重写了AbstractCollection的clear()方法
1 2 3 4 5 6 7 8 9 10 11 12 public void clear () { removeRange(0 , size()); } 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(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 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 boolean addAll (int index, Collection<? extends E> c) { rangeCheckForAdd(index); boolean modified = false ; for (E e : c) { add(index++, e); modified = true ; } return modified; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public boolean equals (Object o) { 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; }
计算哈希码使用31的好处:
31是一个质数 (素数),与数字相乘的结果也是质数,减少哈希冲突
31*i ==32i-i==(i*2^5)-i=(i<<5)-1 ,即31i可以仅使用*移位运算和减法 ,算法效率较高
哈希计算尽量选择较大的数,使得计算出的哈希值较大,减少哈希冲突(不使用15的原因)
31仅有5bits,相乘造成数据移除的概率小(不使用63的原因)