Java之Collection接口介绍与剖析,看完后保证你再也忘不掉

Collection接口概述

Collection是一个接口,继承自Iterable。我们先看一下Iterable接口的源码。

1:Iterable接口源码

Iterable接口有一个Iterator iterator()方法,而Collection继承Iterable,所以我们说Collection依赖Iterator。

1.2 Collection接口

Collection是一个高度封装的集合接口,它提供了所有集合要实现的默认方法接口,我们再看一下Collection接口关系类图。

我们看一下接口源码,了解它有哪些接口和默认实现。

Collection接口源码

packagejava.util;

importjava.util.function.Predicate;

importjava.util.stream.Stream;

importjava.util.stream.StreamSupport;

/**

*这是一个集合分层的根接口。集合代表了一组包含元素的对象。有些集合允许有重复的元素,有些不允许。

*有些集合是有序的有些无序的。jdk不对这个接口提供任何直接的实现,但是再一些直接子接口例如Set和List有实现了某些接口方法。

*所有继承Collection的类必须提供两个默认的构造函数,一个不带参数的、一个带Collection类型参数。

*/

publicinterfaceCollectionextendsIterable{

// 查询操作

/**

*返回集合大小,也就是集合中元素的数量

*/

intsize();

/**

* 如果集合包含元素返回true,即判断集合是否为空

*/

booleanisEmpty();

/**

* 判断集合是否存在某个对象,注意这里参数是个Object,并没有限制为E或其子类

*/

booleancontains(Object o);

/**

* 返回一个迭代器iterator。并没有说明元素的迭代顺序,除非特别的集合有这个要求。

*/

Iteratoriterator();

/**

*将集合转为对象数组,注意这里不是元素数组而是一个Object数组。

*如果集合保证是有序的,那么通过迭代器返回数组有相同顺序

*返回的数组是安全的,也就是说集合有自己的引用,数组开辟新的堆内存,也有自己的引用。所以调

*用者可以随意操作返回的数组。

*这个方法是数组和列表之间的桥梁

*/

Object[] toArray();

/**

* 返回一个集合元素类型的数组。如果集合满足指定的数组并且有足够的空间,则在其中返回此集合

* 否则返回此集合大小的新数组。

* 如果集合有序,那么返回此集合迭代器遍历顺序的数组

* 如果数组大小比集合元素多,那么在数组满足集合元素后在末尾设置为null

* 如果在这个集合中指定数组运行时类型不是运行时元素类型的超类,那么抛ArrayStoreException异常

* 如果指定数组为空,则抛出NullPointerException

*/

 T[] toArray(T[] a);

// 修改操作

/**

* 确保此集合包含特定的元素类型。

* 如果此集合增加元素成功返回true。

* 如果此集合不允许有重复元素并且已经包含所传参数,那么返回false

*

* 支持此操作的集合可能会限制向该集合添加哪些元素。特别的,有些集合会拒绝null元素,有些

* 会对要增加的元素强加一些限制。

* Collection实现类应该在文档中明确指出所有的限制。

* 如果集合以除已经包含元素之外的任何原因拒绝添加特定元素,则必须抛出异常

*(而不是返回false)。这保留了集合在此调用返回后始终包含指定元素的不变式。

*/

booleanadd(E e);

/**

* 如果此集合中存在此元素,那么移除一个特定元素类型的实例。更正式的说,如果集合中包含一个或多个这样的元素,

* 那么删除这样的元素(o==null?e==null:o.equals(e))。如果集合包含指定的元素(或集合因调用而发生改变),那么返回true。

*

* 如果指定元素的类型和集合不相容,抛出ClassCastException异常(可选的限制条件)

* 如果指定元素是null并且这个集合不允许null元素存在,那么抛出NullPointerException异常(可选的限制条件)

* 如果此集合不支持remove操作那么抛出UnsupportedOperationException异常(可选的限制条件)

*/

booleanremove(Object o);

// 容量操作

/**

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

* c集合必须要检查是否被包含在this集合

* 如果指定元素的类型和集合不相容,抛出ClassCastException异常(可选的限制条件)

* 如果指定元素是null并且这个集合不允许null元素存在,那么抛出NullPointerException异常(可选的限制条件)

*/

booleancontainsAll(Collection<?> c);

/**

* 将指定集合的所有元素到this集合中(可选的操作)。

* 如果指定的集合在操作进行时被修改了,那么此操作行为未定义。

* (这意味着如果指定的集合是这个集合,并且这个集合是非空的,那么这个调用的行为是未定义的。)

*

* @参数:c集合包含了要被添加到这个集合的元素

* @返回:如果调用结果改变了this集合返回true

*@throws:如果 addAll操作不被此集合支持,那么抛出UnsupportedOpertaionException异常

*@throws: 如果指定集合包含了空元素而this集合不允许有空元素,那么抛出NullPointerException异常

*@throws:如果this集合阻止hiding集合元素类型添加,那么抛出ClassCastException异常

*@throws:如果指定集合的元素的某些属性阻止将其添加到此集合,则抛出IllegalArgumentException

*@throws:由于插入限制,如果不是所有元素都可以在此时添加,则抛出IllegalStateException异常

*/

booleanaddAll(Collection<? extends E> c);

/**

* 移除此集合中所有的包含在指定集合中的元素(可选的操作)。调用过此函数之后,那么此集合和指定集合将不再包含相同元素。

*@param:包含要从该集合中删除的元素的c集合

*@return:如果此集合因调用而更改那么返回true

*@throws:如果此集合不支持removeAll方法,则抛出UnsupportedOperationException

*@throws:如果集合中一个或多个元素的类型与指定集合不兼容,则抛出ClassCastException(可选的操作)

*@throws:如果该集合包含一个或多个空元素,且指定的集合不支持空元素(optional),或者指定的集合为空,

* 则抛出NullPointerException异常

*/

booleanremoveAll(Collection<?> c);

/**

* 移除此集合中所有符合给定Predicate的元素。在迭代期间或由Predicate引发的错误或运行时异常将被转发给调用方

*@implSpec

* 默认实现使用其迭代器遍历集合的所有元素。每一个匹配的元素使用iterator.remove()来移除。

* 如果集合的iterator不支持移除将会抛出UnsupportedOperationException异常在匹匹厄到

* 第一个元素时。

*@param过滤一个predicate

*@param筛选要删除的元素返回true的Predicate

*@return如果任何一个元素被删除返回true

*@throws指定过滤器为空,抛出NullPointerException

*@throws如果元素没有被删除,或者移除操作不支持,

*  则立即抛出UnsupportedOperationException异常

*@since1.8

*/

defaultbooleanremoveIf(Predicate filter){

//如果filter为null抛出NullPointerException

Objects.requireNonNull(filter);

booleanremoved =false;

finalIterator each = iterator();

//通过迭代器遍历删除,只要删除一个removed就为true

while(each.hasNext()) {

if(filter.test(each.next())) {

each.remove();

removed =true;

}

}

returnremoved;

}

/**

* 只保留此集合中包含在指定集合中的元素(可选的操作)。

* 也就是说,此集合中不包含在指定集合中的所有元素。

*@param:要保留的元素的集合c

*@return:如果此集合改变了返回true

*@throws:如果此集合不支持retainAll,则抛出UnsupportedOperationException异常

*@throws:如果集合中一个或多个元素的类型与指定集合不兼容,则抛出ClassCastException(可选的操作)

*@throws:如果该集合包含一个或多个空元素,且指定的集合不支持空元素(optional),或者指定的集合为空

*/

booleanretainAll(Collection<?> c);

/**

* 移除此集合中所有元素(可选操作),调用此方法后集合里将为空。

*@throws: 如果此集合clear操作不支持将会抛出UnsupportOperationException异常。

*/

voidclear();

// 比较和hash

/**

* 比较指定的对象与此集合是否相等

*

*/

booleanequals(Object o);

/**

*返回这个集合的hashCode。当集合接口没有对Object.hashCode方法的一般协议做任何规定,编程

*人员应该注意在重写equals方法时必须重写hashCode方法,以便满足一般协议对这个

*Object.hashCode方法。特别的,c1.equals(c2)表明c1.hashCode()==c2.hashCode()。

*/

inthashCode();

/**

*一下1.8新增的Spliterator,暂不研究

*/

@Override

defaultSpliteratorspliterator(){

returnSpliterators.spliterator(this,0);

}

defaultStreamstream(){

returnStreamSupport.stream(spliterator(),false);

}

defaultStreamparallelStream(){

returnStreamSupport.stream(spliterator(),true);

}

}

2.3 AbstractCollection类

AbstractCollection是一个实现了Collection接口的抽象类,除了iterator()和size()接口,它提供了一些其他接口的默认实现,其他集合类可以继承此类来复用。

packagejava.util;

publicabstractclassAbstractCollectionimplementsCollection{

/*唯一的构造函数*/

protectedAbstractCollection(){

}

// 查询操作

publicabstractIteratoriterator();

publicabstractintsize();

/**

* 返回size()==0

*/

publicbooleanisEmpty(){

returnsize() ==0;

}

/**

* 实现的contains方法,通过迭代器遍历

*/

publicbooleancontains(Object o){

Iterator it = iterator();

if(o==null) {

while(it.hasNext())

if(it.next()==null)

returntrue;

}else{

while(it.hasNext())

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

returntrue;

}

returnfalse;

}

/**

* 此默认实现,考虑到数组在迭代器遍历过程中大小可能会改变,

* 也就是可能会增加或减少元素怒

*/

publicObject[] toArray() {

// 估计数组大小,并做好变小或变大的准备

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

Iterator it = iterator();

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

if(! it.hasNext())//比期望的元素少,那么调用Arrays.copyOf()方法返回一个新的数组

//Arrays.copyOf方法在Arrays中讲解

returnArrays.copyOf(r, i);

r[i] = it.next();

}

// 判断集合有没有被增加(迭代器改变),如果没有返回数组,如果有调用finishToArray()方法返回数组

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

}

/**

*

*/

@SuppressWarnings("unchecked")

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

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

intsize = size();

T[] r = a.length >= size ? a :

(T[])java.lang.reflect.Array

.newInstance(a.getClass().getComponentType(), size);

Iterator it = iterator();

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

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

if(a == r) {

r[i] =null;// null-terminate

}elseif(a.length < i) {

returnArrays.copyOf(r, i);

}else{

System.arraycopy(r,0, a,0, i);

if(a.length > i) {

a[i] =null;

}

}

returna;

}

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

}

// more elements than expected

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

/**

* 一些VM会在数组中保留头信息,所以要占用8字节空间,头信息大小不能超过8

* 重新分配更大的长度给数组,如果要求的数组大小超过VM限制,会抛出OutOfMemoryError

* 默认值 2147483647 - 8;

*/

privatestaticfinalintMAX_ARRAY_SIZE = Integer.MAX_VALUE -8;

/**

* 重新在toArray方法中,如果iterator返回了比期望中的大小更多的元素时,重新给数组分配空间来完成填充数组。

*@param之前的已经被填满的数组

*@param操作中集合的iterator

*@return除了给定的数组之外,增加了从迭代器中获取的元素,并修正数组长度

*/

@SuppressWarnings("unchecked")

privatestatic T[] finishToArray(T[] r, Iterator it) {

inti = r.length;//被填充满的数组长度(原始集合大小)

while(it.hasNext()) {

intcap = r.length;

if(i == cap) {//第一次(刚进来的时候)一定为true,那么分配新的数组大小

intnewCap = cap + (cap >>1) +1;//右移一位+1再加上原大小

if(newCap - MAX_ARRAY_SIZE >0)

//新数组大小大于集合默认最大值,调用hugeCapacity()方法重新分配,值为Integer.MAX_VALUE

newCap = hugeCapacity(cap +1);

r = Arrays.copyOf(r, newCap);

}

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

}

// 修正数组多余的空间,如果正好直接返回,否则调用Arrays.copyOf()方法

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

}

privatestaticinthugeCapacity(intminCapacity){

if(minCapacity <0)// 内存溢出

thrownewOutOfMemoryError

("Required array size too large");

return(minCapacity > MAX_ARRAY_SIZE) ?

Integer.MAX_VALUE :

MAX_ARRAY_SIZE;

}

// 修改操作

/**

* 此操作总是抛出 UnsupportedOperationException

*@throwsUnsupportedOperationException {@inheritDoc}

*@throwsClassCastException            {@inheritDoc}

*@throwsNullPointerException          {@inheritDoc}

*@throwsIllegalArgumentException      {@inheritDoc}

*@throwsIllegalStateException         {@inheritDoc}

*/

publicbooleanadd(E e){

thrownewUnsupportedOperationException();

}

/**

* 通过集合迭代器查找元素,如果找到调用iterator.remove()方法删除元素。

* 删除一个就返回true

*/

publicbooleanremove(Object o){

Iterator it = iterator();

if(o==null) {

while(it.hasNext()) {

if(it.next()==null) {

it.remove();

returntrue;

}

}

}else{

while(it.hasNext()) {

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

it.remove();

returntrue;

}

}

}

returnfalse;

}

// Bulk Operations

/**

* 判断此集合是否包含指定集合所有元素,有一个没有返回false

*/

publicbooleancontainsAll(Collection<?> c){

for(Object e : c)

if(!contains(e))

returnfalse;

returntrue;

}

/**

* 调用add(E e)方法添加指定集合到此集合中

*

*@see#add(Object)

*/

publicbooleanaddAll(Collection<? extends E> c){

booleanmodified =false;

for(E e : c)

if(add(e))

modified =true;

returnmodified;

}

/**

* 这个方法将从此集合中删除指定集合的所有元素,通过迭代器删除。

*@throwsUnsupportedOperationException {@inheritDoc}

*@throwsClassCastException            {@inheritDoc}

*@throwsNullPointerException          {@inheritDoc}

*

*@see#remove(Object)

*@see#contains(Object)

*/

publicbooleanremoveAll(Collection<?> c){

Objects.requireNonNull(c);

booleanmodified =false;

Iterator it = iterator();

while(it.hasNext()) {

if(c.contains(it.next())) {

it.remove();

modified =true;

}

}

returnmodified;

}

/**

* 此集合中保留指定集合的所有元素,也就是说调用此方法之后,此集合中删除了不存在指定集合中

*的元素

*

*/

publicbooleanretainAll(Collection<?> c){

Objects.requireNonNull(c);

booleanmodified =false;

Iterator it = iterator();

while(it.hasNext()) {

if(!c.contains(it.next())) {

it.remove();

modified =true;

}

}

returnmodified;

}

/**

* 清空集合中所有元素

*@throwsUnsupportedOperationException {@inheritDoc}

*/

publicvoidclear(){

Iterator it = iterator();

while(it.hasNext()) {

it.next();

it.remove();

}

}

//  String conversion

/**

* 集合的toString方法,所有继承AbstractCollection的类都有此方法

*/

publicStringtoString(){

Iterator it = iterator();

if(! it.hasNext())

return"[]";

StringBuilder sb =newStringBuilder();

sb.append('[');

for(;;) {

E e = it.next();

//如果将自己这个集合添加到自己,就会打印(this Collection)

sb.append(e ==this?"(this Collection)": e);

if(! it.hasNext())

returnsb.append(']').toString();

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

}

}

}

AbstractCollection类默认实现的方法,在上面源代码中我都已经讲解过了,很多常用的集合都会使用 默认实现,比如常用的toString方法,我们在输出ArrayList时调用的就是此方法。

注:文章所有权归原作者所有,如果有侵权,请联系小编删除。

如果您前端学习的过程中遇到难题,欢迎关注微信公众号【筑梦前端】,大家一起交流讨论解决!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,365评论 0 4
  • 四、集合框架 1:String类:字符串(重点) (1)多个字符组成的一个序列,叫字符串。生活中很多数据的描述都采...
    佘大将军阅读 734评论 0 2
  • 写在前面自开始在公司实习以来,经常都要用到集合框架。不仅后台要用,在前台做数据交互的时候用得也多。所以我想着是时候...
    EakonZhao阅读 3,257评论 0 12
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX阅读 869评论 0 1
  • 1、《狗武士》 130千字 2、《柳林风声》145千字 3、 《皮皮鲁和有鬼电车》120千字 4、《装在口袋里的爸...
    AZF谁与争峰阅读 1,024评论 0 1