Collection集合了解一下

集合家族

image

Collection接口

Collection接口Api一览

image

由图中我们可以看出:

  • 重写了Iterable接口的iterator方法。
  • 重写了Object类的equals和hashCode方法。
  • 定义了一系列待实现方法。

为什么重写Iterable接口的iterator方法

image

很直观。我们一看注释其实就能大概明白Java设计人员的思路,其实Iterable接口可以看成许多容器类共同特性被提取出来做了接口。而相对于不同容器,这个共有特性的具体实现细节又不同。既然不同所以又要自己定义自己系列的迭代器规则,并让所有实现类都遵循这个规则。

对于Collection接口来说,它规定子接口及其实现类都必须满足它重新设定的规则。

Returns an iterator over the elements in this collection. There are no guarantees concerning the order in which the elements are returned

针对于集合中的所有元素返回一个该集合的迭代器。 但是该迭代器无法保证元素间具有顺序性。(除非这个集合是某个具有这一特性的类的实例)

Collection Api 详解

这里大家可以看Api文档,讲的比我自己理解的好很多。这里我只是想顺便锻炼一下自己看英文文献的能力。并且很多不懂的我都是照搬了Api文档

  • boolean add(E e)

向集合中添加一个元素。集合更改则添加成功返回true,如果该集合不允许重复并且已经包含指定的元素。返回false。部分子类的add方法可能会限制添加到集合中的元素类型,或者不会将NULL添加到集合中。

  • boolean addAll(Collection<? extends E> c)

将指定集合中的所有元素添加到此集合中。在添加过程中如果被添加的集合发生了更改,addAll方法不具有幂等性。

  • void clear()

清空掉集合中的所有元素

  • boolean contains(Object o)

如果集合中包含指定元素那么返回true。特别的,如果集合中也包含NULL元素的时候并且要查找的元素也是NULL的时候也返回true。

  • boolean containsAll(Collection<?> c)

如果该集合中包含指定集合中的所有元素的时候返回true。

  • boolean isEmpty()

如果集合中没有元素返回true。

  • boolean remove(Object o)

删除集合中的指定的元素。如果存在NULL,也删除。

  • boolean removeAll(Collection<?> c)

删除当前集合中所有等于指定集合中的元素。

  • boolean retainAll(Collection<?> c)

仅保留该指定集合中存在的所有元素。其余删除

  • int size()

返回该集合中元素的个数。如果超过了Integer.MAX_VALUE,那么返回Integer.MAX_VALUE。

  • Object[] toArray()

这个方法是集合和数组转化的桥梁。

见名知意,返回包含此集合中所有元素的数组。如果这个集合的迭代器保证元素有序,那么该方法与其迭代器中元素顺序一致。并且该方法返回的数组是拷贝出来的(某些集合底层数组实现,区别这个),可以进行任意的更改。

  • <T> T[] toArray(T[] a)

该方法可以对返回的数组类型进行精确控制。而非像toArray方法一样返回Object[]

返回集合中所有元素到该数组中。如果这个数组可以容纳下的话,否则返回一个新new的数组,容量和集合中元素数量一致。如果指定的数组容量大于集合中元素个数,数组空闲位置填NULL。如果这个集合的Iterator具有顺序性的话,数组元素顺序与该迭代器一致。

Collection接口在Java8中的函数扩展

新增抽象方法:


image

新增重写方法splIterator以及继承方法forEach。


image

Iterator 接口

从刚才的Colllection接口的结构体中我们可以看出,该Collection接口实现了Iterable接口,说明了Collection接口是可迭代的。而这个Iterable接口又只有一个iterator方法。返回值是Iterator对象。即返回的是对应实现类的迭代器对象。

image

如图,Iterator接口只有三个抽象函数。

首先我们先来对Iterator接口了解一下:

image

Iterator Api详解

  • boolean hasNext()

如果迭代器中还有元素那么返回true。

  • E next()

返回迭代器中游标的下一元素

  • void remove()

从迭代器指向的 collection 中移除迭代器返回的最后一个元素。每次调用 next 后只能调用一次此方法。如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。

ArrayList的自定义迭代器

我们拿了一个Collection接口的实现类来看了一下。

image

ArrayList写了一个内部类Itr来实现Iterator接口作为自己的迭代器。

变量:

  • cursor:迭代器下一个要返回的元素的索引
  • lastRet:迭代器最后一个返回的元素的索引
  • expectedModCount:期望中ArrayList集合的底层数组容器的修改次数,来和父类AbstractList中设定的变量modCount来进行比较。

方法:

  • hasNext:判断游标是否指到了size即可。因为底层容器是数组所以size位置没有元素当游标指到的时候就是迭代器结束迭代的时候。
  • next:首先判断容器是否在Itr初始化之后就已经被其他线程进行了更改。如果是那么就会根据checkForComodification方法的判断规则来跑出一个异常。然后就是通过游标来对容器进行迭代,并动态的修改lastRet的值。
  • remove: 因为是更改操作,先判断一下容器是否被动过。然后调用该ArrayList类的实例的remove方法删除掉指定索引处的元素。此时动态的维护cursor和lastRet,expectedModCount变量。此处可有看出Iterator接口的remove方法的解释是什么意思了。
  • checkForComodification:该方法就是简单的对expectedModCount变量和AbstractList类中的modCount变量进行判断看是否容器被其他线程更改了。这也就是为什么Iterator接口的remove方法的释义说迭代器的行为是不确定的。这里ArrayList由于是线程不安全的类,所以在其迭代器中设定了如果线程间冲突时的处理规则。

List 接口

List接口Api一览

image
  • 重写了Collection接口的一些列函数。
  • 继承了add和addAll两个函数的规则。
  • 新增了一些列函数。

List集合的特点

image

和Set集合最大的不同即红框中所述:

  • 有序
  • 允许重复元素

从Api列表中我们可以看到List接口定义了一个listIterator函数,返回一个ListIterator接口。该接口继承自Iterator接口,并提供了更多的函数。

ListIterator接口

image

从ListIterator接口的Api描述中总结出的几点就是:

  • 相比于hasNext函数多了一个对应的hasPrevious函数,来检测游标指向的元素是否具有前驱元素。
  • 相比于next函数多了一个previous函数,来获取游标指向的元素的前一位元素。
  • 多了nextIndex和previousIndex函数,用来返回迭代器下一元素和前一迭代过的元素的索引。
  • 多了set函数和add函数,set函数允许替换掉previous和next函数操作后返回的元素。add函数允许将元素插入到容器中游标前的位置。

List常见实现类

image
  • ArrayList:
    底层数据结构是数组。线程不安全
  • LinkedList:
    底层数据结构是链表。线程不安全
  • Vector:
    底层数据结构是数组。线程安全

Set 接口

Set接口Api一览

image
  • 并没有新增自己的函数
  • 重写了Collection接口的部分函数
  • 继承了add函数和addAll函数

Set集合特点

image

相比于List集合最大的区别:

  • 不包含重复元素。

这里我们强调一下,有些地方说Set集合是无序的,其实是不严谨的。可以看到jdk注释中是没有指明这一点的,那么List集合的注释中的有序和有些人常说的Set集合是无序的是什么意思呢?


首先要搞清楚、Java中有序和无序的概念:

有序指的是存储顺序与添加顺序相同,并且可以通过下标访问,List就是这样。

无序刚好相反,指的是存储顺序与添加顺序无关,没有下标,当然也不可能通过下标访问,Set就是如此。

这里需要注意的是,有序、无序中的“序”与我们平常所说的“顺序”无关。

而TreeSet是无序,但又是排好序的。即添加顺序与存储顺序无关,但是其中的对象实现了排序。


Set集合常用子类

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

推荐阅读更多精彩内容