java集合类程序代码_java集合类源码学习二

我们查看Collection接口的hierarchy时候,可以看到AbstractCollection这样一个抽象类,它实现了Collection接口的部分方法,Collection集合系列的各个集合类都继承于该抽象类。我们来看看这个类:

public abstract class AbstractCollection implements Collection {

protected AbstractCollection() {

}

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)

return true;

} else {

while (it.hasNext())

if (o.equals(it.next()))

return true;

}

return false;

}

public Object[] toArray() {

// Estimate size of array; be prepared to see more or fewer elements

Object[] r = new Object[size()];

Iterator it = iterator();

for (int i = 0; i < r.length; i++) {

if (! it.hasNext()) // fewer elements than expected

return Arrays.copyOf(r, i);

r[i] = it.next();

}

return it.hasNext() ? finishToArray(r, it) : r;

}

@SuppressWarnings("unchecked")

public T[] toArray(T[] a) {

// Estimate size of array; be prepared to see more or fewer elements

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()) { // fewer elements than expected

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();

}

// more elements than expected

return it.hasNext() ? finishToArray(r, it) : r;

}

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

@SuppressWarnings("unchecked")

private static 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;

// overflow-conscious code

if (newCap - MAX_ARRAY_SIZE > 0)

newCap = hugeCapacity(cap + 1);

r = Arrays.copyOf(r, newCap);

}

r[i++] = (T)it.next();

}

// trim if overallocated

return (i == r.length) ? r : Arrays.copyOf(r, i);

}

private static int hugeCapacity(int minCapacity) {

if (minCapacity < 0) // overflow

throw new OutOfMemoryError

("Required array size too large");

return (minCapacity > MAX_ARRAY_SIZE) ?

Integer.MAX_VALUE :

MAX_ARRAY_SIZE;

}

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;

}

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 retainAll(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 String toString() {

Iterator 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(' ');

}

}

}

从它的代码里我们可以看到,它有一个最大长度,是Integer的最大值减去8,至于为什么减8,是因为有些JVM会在数组里保存几个关键字符。我们再看这个contains方法,我很好奇的是,既然参数是Object类型,那么就包括了null,为什么判断的时候还要把null单独拿出来,这个疑问不知哪个大佬能给我解释一下。

再看toArray的不带参方法,new了一个和size()方法表示的长度一样长的Object数组r,还弄了一个迭代器出来,然后用for来循环r数组的每一个下标,并在每一次循环中判断迭代器的hasNext()是否为false,如果为false则说明当前集合长度比r数组短,则用Array的copyOf()方法把r数组放到一个长度为i的数组里,这样就不浪费多余的空间了。最后判断如果hasNext()还为true,则说明当前集合长度比r数组长,就用finishToArray()方法返回一个Object数组。至于为什么比较过和size()的大小之后还有这种操作,上面注释有说明,是迭代的时候假如对元素有增删操作,会导致长度有变化。finishToArray(T[] r, Iterator> it)方法把数组r扩容之后往里面添加迭代器后续元素,可以看到hugeCapacity这个玩意,当数组长度超过Integer最大值减8的时候,就用Integer的最大值,这样数组的长度是不能超过2^31的,毕竟数组下标使用int数字表示的。带参的toArray方法差不多意思,是可以将集合转化成指定类型的数组。

add()方法会直接抛出异常,说明AbstractCollection是不允许添加元素的,那么一定是在具体实现类里实现的这个方法。至于其他的方法,看一下就明白了。

接着我们来看看public abstract class AbstractList extends AbstractCollection implements List,这是list的抽象类,继承自AbstractCollection,实现List接口的部分方法。源码就不贴了,现在重点来看一下内部类Itr,这是一个迭代器的实现类。里面定义了三个变量:游标cursor、最近一次调用返回的索引lastRet和期望得到的修改次数expectedModCount。里面实现了迭代器的三个方法,注意next()和remove()方法里都调用了这么一个方法checkForComodification(),这个用来比较expectedModCount和modCount,如果不同就抛出异常ConcurrentModificationException,这个意思是如果在迭代操作的时候,如果有用非迭代器的操作对集合做了修改,那么就会抛出异常。对于modCount,我们可以在AbstractList的子类中看到,每次对集合做了操作,modCount就会加一。

public static void main(String[] args) {

List list = new ArrayList();

list.add(11);

list.add(12);

list.add(13);

list.add(14);

list.add(15);

Iterator itr = list.iterator();

while(itr.hasNext()) {

if(itr.next() == 13) {

itr.remove();

}

}

System.out.println(list);

}

在迭代的时候用迭代器的remove操作就不会报错,如果在增强for循环中,用了ArrayList自带的remove,就会报异常了。下面的内部类ListItr是一个ListIterator的实现类,可以往前往后迭代,还有多了几个方法,代码都很简单。subList()截取一段子序列,支持往前往后截取。下面还有个SubList类,里面有个往后截取一段子序列的方法,其他的起始都是用的父类的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值