集合类源码之AbstractCollection(二)

import java.util.Arrays;
import jdk.internal.util.ArraysSupport;

/**
 * @Classname AbstractCollection:实现了一些方法,也定义了几个抽象方法留给子类实现,因此是个抽象类
 * @note:Collection接口的定义和继承的Iterable都可以在这个抽象类中实现,可以减少实现类需要实现的方法
 * @note:如果要实现一个不可修改的集合,只需要重写iterator和size接口
 * @note:如果要实现可以修改的集合,还必须重写add方法(默认会抛出异常),返回的Iterator还需要实现remove方法
 * @date 2021年7月6日 下午3:32:49
 * @Version 1.0
 */
public abstract class AbstractCollection<E> implements Collection<E> {
//	默认的构造函数是protected,因此会推荐子类去创建一个无参的构造函数
	protected AbstractCollection() {}
	/**
	 * 仅有的两个抽象方法
	 *@Description:子类实现迭代器和子类大小,子类必须以自己的方式实现这两个方法
	 */
	public abstract Iterator<E> iterator();
	public abstract int size();
//	实现判断集合元素是否为空
	public boolean isEmpty() {
//		调用子类实现的size()方法
		return size() == 0;
	}
//	实现判断集合是否包含该元素,因为iterator的存在,进行一致性封装,对象的比较是通过equals()
	public boolean contains(Object o) {
//		获取子类实现的迭代器,挨个遍历和比较
		Iterator<E> it = iterator();
		if(o==null) {
			while(it.hasNext()) {
//				说明AbstractCollection实现类支持null元素
				if(it.next()==null) {
					return true;
				}
			}
				
		}else {
			while(it.hasNext()) {
//				传入的这个元素类需要重写equals()方法
				if(o.equals(it.next())) {
					return true;
				}
			}
		}
		return false;
	}
//	实现判断集合中是否包含该集合的所有元素
	public boolean containsAll(Collection<?> c) {
		Iterator<?> it = c.iterator();
//		挨个遍历指定集合,这里的时间复杂度是次方阶
		while(it.hasNext()) {
			if(!c.contains(it.next())) {
				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;
				}
			}
		}
	}
//	实现两个集合中保留共有的元素
	public boolean retainAll(Collection<?> c) {
		boolean result = false;
		Iterator<?> it = c.iterator();
//		挨个遍历指定集合,这里的时间复杂度是次方阶
		while(it.hasNext()) {
//			调用的是Collection接口的contains()?
			if(!c.contains(it.next())) {
				it.remove();
				result = true;
			}			
		}
		return result;
	}
	/**
	 * AbstractCollection中默认不支持添加单个元素,如果直接调用会报错
	 *@Description:默认是抛出异常,都是让子类去实现
	 */
	public boolean add(E e) {
        throw new UnsupportedOperationException();
    }
//	实现在集合中添加一个集合
	public boolean addAll(Collection<? extends E> c) {
		boolean modified = false;
//		获取待添加对象的迭代器
		Iterator<? extends E> it = c.iterator();
//		挨个遍历,如果add()没有实现的话,addAll()也不会实现
		while(it.hasNext()) {
			if(add(it.next())){
				modified = true;
			}
		}
	}
//	实现清空集合
	public void clear() {
//		获取子类实现的迭代器,挨个遍历删除
		Iterator<E> it = iterator();
		while(it.hasNext()) {
			it.next();
//			单线程使用迭代器的remove()方法不会导致fail-fast
			it.remove();
		}
	}
	/**
	 * 实现集合转换成数组
	 *@Description:这里返回的顺序和Iterator顺序一致,在这里实现是方便实现类互相转换
	 */
//	先根据当前集合大小声明一个数组
	public Object[] toArray() {
		// 集合元素的大小赋值给数组大小后,可能会存在同步线程修改集合
		Object[] object = new Object[size()];
		Iterator<E> it = iterator();
		// 迭代器师集合的迭代器,但最多访问的位置是数组的大小位置,如果没有访问到数组的大小位置,则表明集合元素减少了
		for(int i = 0; i < object.length; i++) {
            // 集合元素没有数组那么多,说明不需要那么大的数组
			if(!it.hasNext()) {
				// 这里很明显是静态方法
                // 扩容的主要手段是Arrays.copyOf()方法,即新建一个原数组的拷贝,并修改原数组,指向这个新建数组。原数组自动抛弃(java垃圾回收机制会自动回收)
				return Arrays.copyOf(object,i);
			}
			// 将集合元素赋值给数组
			object[i] = (Object) it.next();
		}
        // 元素比从SIZE()中获取的更多,就需要进一步调整数组的大小
	    return it.hasNext() ? finishToArray(object,it) : object;
    }
//	跟上一个转换数组相比,通过传入指定类型的数组可以明确返回数组的类型
    @SuppressWarnings("unchecked") // 这里是注解
	public <T> T[] toArray(T[] a) {
        // size就是集合的大小
        int size = size();
        // 当传入数组的大小大于集合的大小时,r数组就是a数组,否则定义一个跟数组a同类型的数组r,但数组大小却是集合的大小
        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数组,直接就返回a数组
                    r[i] = null; 
                } else if (a.length < i) {
                	// 传入的数组长度小于当前r数组有元素的长度,则只需要去掉r数组有null部分的长度
                    return Arrays.copyOf(r, i);
                } else {
                	// 传入的数组长度大于等于r数组,把r数组赋值给a数组,若没填满,则剩余长度赋值为null,然后返回a数组
                    System.arraycopy(r, 0, a, 0, i);
                    if (a.length > i) {
                        a[i] = null;
                    }
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        // 当集合元素获取迭代器后数据变多了,则将剩余的元素传入finishToArray()方法填入新的数组中,当获取迭代器后数量不变,则将数据赋值给r数组,并返回r数组
        return it.hasNext() ? finishToArray(r, it) : r;
    }
//	进一步调整数组的大小
	private static <T> T[] finishToArray(T[] object,Iterator<?> it) {
//		记录当前大小
		int len = object.length;
		int i = len;
		while(it.hasNext()) {
//			数组长度不够,继续分配
			if(i == len) {
//				按Object长度的1.5倍进行扩容
				len = ArraysSupport.newLength(len,1,(len>>1)+1);
//				对object数组进行扩容
				object = Arrays.copyOf(object, len);
			}
//			赋值,进入下一轮循环
			object[i++] = (T) it.next();
		}
//		由于之前扩容是1.5倍进行的,最后将其设置到和object实际需要的相同
		return (i==len)?object:Arrays.copyOf(object, i);
	}
	/**
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        
//      超过了最大容量,MAX_ARRAY_LENGTH=Integer.MAX_VALUE-8
 
        if (newLength - MAX_ARRAY_LENGTH <= 0) {
            return newLength;
        }
        return hugeLength(oldLength, minGrowth);
    }

private static int hugeLength(int oldLength, int minGrowth) {
        int minLength = oldLength + minGrowth;
        if (minLength < 0) {
            throw new OutOfMemoryError("Required array length too large");
        }
        if (minLength <= MAX_ARRAY_LENGTH) {
            return MAX_ARRAY_LENGTH;
        }
        return Integer.MAX_VALUE;
    }	
	 */
	/**
	 *@Description:toString()通过StringBuilder拼接了每个元素的toString完成的
	 */
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        // 无限循环
        for (;;) {
            E e = it.next();
            // 避免在集合中出现a.add(a)导致无限循环调用toString()导致堆溢出
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
            	// 调用StringBuilder自身的toString()完成打印
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值