Java源码解析之接口Collection

Java源码解析之接口Collection

一、图示

二、方法定义

我们先想一想,公司如果要我们自己去封装一些操作数组或者链表的工具类,我么需要封装哪些功能呢?不妨就是统计其 大小,增删改查、清空或者是查看否含有某条数据等等。而collection接口就是把这些通常操作提取出来,使其更全面、更通用,那现在我们就来看看其源码都有哪些方法。

//返回集合的长度,如果长http://度大于Integer.MAX_VALUE,返回Integer.MAX_VALUE

int size();

//如果集合元素总数为0,返回true

boolean isEmpty();

//判断集合中是否包含指定的元素,其依据是equals()方法

boolean contains(Object o);

//返回一个包含集合中所有元素的数组

Object[] toArray();

//与上个类似,只是增加了类型的转换

T[] toArray(T[] a);

//向集合中加入一个元素,如果成功加入则返回true,如果加入失败,或者因集合本身已经包含同个元素而不再加入时,返回false

boolean add(E e);

//从集合中删除指定元素的单个实例

boolean remove(Object o);

//如果集合包含指定集合中的所有元素,返回true

boolean containsAll(Collection> c);

//把指定集合中的所有元素添加到集合中,但在此期间,如果指定的集合发生了改变,可能出现意想不到的事情

boolean addAll(Collection extends E> c);

//从集合中删除所有包含在指定集合中的元素

boolean removeAll(Collection> c);

//仅保留集合中包含在指定集合中的元素

boolean retainAll(Collection> c);

//清空集合

void clear();

//将此方法抽象,是保证所有子类都覆写此方法,以保证equals的正确行为

boolean equals(Object o);

//同上

int hashCode();

//这个方法在JDK1.8中提供了默认的实现,会使用Iterator的形式删除符合条件的元素

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;

}

三、超级实现类 AbstractCollection

通过以上的学习,我们可以知道在collection接口中,有很多通用的方法,根据现有的定义以及继承的Iterable接口,都可以在抽象方法中实现,这样就可以减少具体实现类需要实现的方法,所以就有了这么一个类–AbstractCollection。

首先我们来看看api文档对这个类的大概描述:

如果要实现一个不可修改的集合,只需要重写Iterator和size接口就可以了,并且返回的Iterator需要实现hasNext和Next。而要实现一个可以修改的集合,还必须重写add方法,返回的Iterator还要实现remove接口。

接下里我们来看看其方法定义

//这个毫无疑问,是可以直接获取的

public boolean isEmpty() {

return size()==0;

}

//这个方法因为Iterator的存在,可以进行一致性封装,这里需要注意的是对象的比较是通过equals方法,因为调用到了it.next()与it.hasNext(),这也是为什么文档注释会写实现集合类需要重写Iterator的这两个方法。

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;

}

//和contains类似,也是通过Iterator实现的,但其会调用it.remove()方法,这也是为什么文档注释会写实现可以修改的集合类时需要重写Iterator的remove方法。

public boolean remove(Object o) {

//...省略,这里调用了it.remove()方法

}

还有很多方法也用到了iterator的特性,例如containAll、addAll等等,这里就不一 一说明了。

除此之外,还有一个toArray方法,方法实现还有一些略微不同:

//这个实现相对复杂一些,可以看到扩容最主要的手段是Arrays.copyOf()方法,

//也就是需要将原数组通过复制到新的数组中来实现的。

//注意这里返回的顺序和Iterator顺序一致

//在这里实现是为了方便不同具体实现类互相转换,我们在后续会多次见到此方法

public Object[] toArray() {

//先根据当前集合大小声明一个数组

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

Iterator it=iterator();

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

    //集合元素没那么多,说明不需要那么大的数组

    if (! it.hasNext()) 

        return Arrays.copyOf(r, i); //仅返回赋完值的部分

    r[i]=it.next();

}

//元素比从size()中获取的更多,就需要进一步调整数组大小

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

}

private static T[] finishToArray(T[] r, Iterator> it) {

//记录当前大小

int i=r.length;

while (it.hasNext()) {

    int cap=r.length;

    //r的长度不够,继续分配

    if (i==cap) {

        //扩充方式为cap+cap/2+1,也就是1.5倍扩容

        int newCap=cap + (cap >> 1) + 1;

        // 超过了最大容量,MAX_ARRAY_SIZE=Integer.MAX_VALUE-8

        if (newCap - MAX_ARRAY_SIZE > 0)

            //重新设置cap的值

            newCap=hugeCapacity(cap + 1);



        //对r进行扩容

        r=Arrays.copyOf(r, newCap);

    }

    //赋值,进入下一轮循环

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

}

// 由于之前扩容是1.5倍进行的,最后再将其设置到和r实际需要的相同

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;

}

//和toArray()方法类似,就不再赘述,具体可以查看源码

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

//...

}

除了这些,我们再来看看AbstractCollection是怎么实现toString方法的吧+

其是通过StringBuilder拼接了每个元素的toString完成的,不是很复杂。

我们来看看源码吧

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 JyqCtUoq63; "(this Collection)" : e);

    if (! it.hasNext())

        return sb.append(']').toString();

    sb.append(',').append(' ');

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值