Java Collection

第一篇技术博客,有错误的地方希望网友指出。


这边博客的主要内容是分析java的Collection接口、它的一个抽象类AbstractCollection.


一、Collection接口

package java.util;
public interface Collection<E> extends Iterable<E> {
    int size();	//返回大小
    boolean isEmpty();	//是否为空
    boolean contains(Object o);	//集合中是否包含某对象
    Iterator<E> iterator();  //迭代器(用于遍历)
    Object[] toArray(); //装换为数组  java中的集合都是由数组实现的
    <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);  //移除全部
    boolean retainAll(Collection<?> c);  //保留所有(移除其他的)
    void clear(); //清除全部
    boolean equals(Object o); //相等
    int hashCode(); //哈希值
}

Collection 接口是所有集合的root interface,接口中共有以上的方法,对于以上方法,不同的子接口会有不同的实现。
Collection 接口主要包含一些基本的遍历和增删改查等。

二、AbstractCollection抽象类

AbstractCollection对Collection对象的部分方法进行了实现。

2.1 属性


   /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;


这里定义了集合的最大值,为整形的最大值减8,api的文档里说由于有的vm对于数组需要头文件,所有这个可能是在Integer最大值的基础上那减去8的原因。

2.2 方法

2.2.1 contains

 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;
    }

contains方法,集合是否包含某个对象,包含返回true,否则返回false。 方法开始会判断o是否为null,因为如果o为null,则调用.equals方法时会抛nullpointer异常。如果不为null,利用迭代器遍历集合,调用o的equals方法去比较,看是否存在于集合中(注:Object的equals方法用的==比较).

 public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

containsAll 方法,对集合中的每个元素做contains处理。


2.2.2 toArray

 public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
        Object[] r = new Object[size()];
        Iterator<E> 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;
    }
toArray方法是将集合装换为对象的数组,通过size()方法拿到当前集合中对象的个数,然后通过迭代器遍历集合,将集合填入数组中。
这本来是个很简单的过程,但是由于Collection接口本身是未同步的,所以size方法得到的个数和迭代器中的个数未必相等。当迭代器中的个数少于定义的数组时,值返回数组的一部分。
当迭代器中的个数多余数组时,则调用了finishToArray方法:
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; //对数组扩容
                // 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);
    }
该方法中先对数组进行扩容,同时会检查数组大小是否超过最大值,如果超过了就调用hugeCapacity方法对数组的大小进行控制,最后把原数组拷贝到新扩容的数组中。当然,当i值又到达了容器的容量,又会重新扩容。最后,会看下数组的大小是否超过迭代器,如果超过就做trim处理。

对于toArray(T[] a)方法是对toArray()方法基础上加上了泛型限制:
 public <T> 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);  //if a's size is smaller than elements size, create a larger array
        Iterator<E> 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;
    }
该方法首先检查a数组是否比集合中个数多,如果多则将a赋给r;如果少,则利用反射重新建一个size大小的数组赋给r。进行r的大小次迭代,迭代器中有值,则赋予数组r;如果迭代器中没有值了,这说明,在迭代期间,已经进行了删除操作,数组元素减少了。
此时,如果r就是a,则数组r中其余的值用null填充;如果a的值比i小,说明r是新建的,我们只需要返回r的一部分就可以了;第三种情况,a的length大于等于当前的i,把r中的数组copy回a中,如果a的length大于i,其余的用null填充。
最后的情况是迭代器中个数多余r,则依然调用finishToArray()。



2.2.3 remove

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;
    }

迭代,如果o为null,找到第一个为null的移除;如果不为null,找到第一个equals的对象,移除。由于null调用equals会报异常,所以null要做特殊处理。



2.2.4 其他



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) {
        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) {
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

这几个方法,只要原集合发生改变就返回TRUE,retainAll是保留给定集合中的对象,移除其他的。






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值