集合--基础知识

集合

集合类是一种工具类,存储数量不等的对象,可以实现栈,队列等数据结构。可以分为:Set:无序,不可重复的集合; List:有序,重复的集合; Queue:队列集合实现; Map:具有映射关系的集合 四种。
集合类主要由:Collection和Map两个接口派生而出.
Map保存的的每项数据都是由key-value对即两个值组成,key用来标识集合里面的每项数据并且不可以重复,根据key值来获取value数据。

Stream

对java集合进行操作,将要处理的集合的元素看成一种流,流在管道中传输,在管道的节点上进行处理,并支持聚合操作。stream的聚合、消费或收集操作只能进行一次,再次操作会报错。

Set集合

Set集合不能记住元素的添加顺序,不允许包含重复元素。
所有Set接口的内部都是Map做支撑,

  1. HashSet

按照Hash算法来存储集合中的元素,底层的数据结构是Hash表。
HashSet不是同步的。集合的元素值可以是空。
根据hashCode值决定元素在集合中的存储位置,HashSet判断两个对象相等的标准:两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。

两个对象的hashCode值不同,但是两个对象的equals()方法返回相同,会把两个对象保存在hash表的不同位置。
两个对象hashCode值相同,但是equals()方法比较不同,会在同一个位置用链式存储结构保存多个对象。
重写hashCode()方法的基本规则
两个对象通过equals()方法比较返回true,这两个对象的hashCode值也应该相同。

LinkedHashSet:是HashSet的子类。也是根据hashCode值来决定元素在集合中的存储位置。使用双重链表维护元素的插入次序。遍历集合中的元素时会按元素的添加顺序来访问集合中的元素。

  1. TreeSet

是SortedSet接口的实现类,可以确保集合元素处于排序状态。不是根据元素的插入顺序进行排序,根据实际值的大小进行排序
TreeSet采用红黑树的数据结构来存储集合元素。分为自然排序和定制排序。
自然排序:TreeSet调用集合元素的comparaTo()方法来比较元素之间的大小,然后按升序排列敲重点:1. 加入TreeSet的元素都要实现Comparable接口 2.加入的最好都是同一个类型的元素。3. 两个元素相等的依据是两个对象的comparaTo()方法返回为0;4. 注意不要修改可变对象的实例变量。
两个对象通过equals()方法返回true时,两个对象的comparaTo()方法比较应返回0。

定制排序:在创建TreeSet集合时,创建一个Comparator对象,与TreeSet集合关联,Comparator负责排序逻辑,通过Comparator接口的帮助,通过利用该函数式接口的compara()方法来实现。

  1. EnumSet

为枚举类设计的集合类,所有元素必须是指定枚举类型的枚举值。是有序的集合,以枚举值在Enum类中的定义顺序来决定集合元素的顺序。不允许加入null元素。EnumSet没有暴露任何构造器来创建该类的实例。
这三个Set的实现类都是线程不安全的。

List集合

代表元素有序可以重复的集合。每个元素都有其对应的顺序索引,通过索引来访问指定位置的元素。List判断两个对象相等的标准:通过equals()方法比较返回true即可。

List的listIterator()方法:返回一个ListIterator对象,ListIterator接口继承自Iterator接口,提供了操作List集合的方法。ListIterator增加了向前迭代的功能,还可以向List集合里面添加元素
两个实现类:ArrayList和Vector,都是基于数组实现的List类。封装了一个动态的,允许再分配的Object[]数组,可以设置数组的长度,当数组中的元素超过设置的数组长度时,数组长度会增加
创建时不指定集合的大小时,动态的Object[]数组的长度默认为10。

ArrayList:是线程不安全的,
Vector:是线程安全的,性能低于ArrayList。

ArrayDeque也是List的实现类,同时也实现了Deque接口。实现了Deque接口,因此可以当作栈来使用,它的底层也是基于数组的实现

Queue集合

用于模拟队列这种数据结构。

  1. PriorityQueue

队列的实现类,保存队列元素的顺序不是按加入队列的顺序,是按照队列元素的大小进行重新排序。不允许加入null元素。有两种排序方式:自然排序和定制排序。

  1. Deque接口

是Queue接口的子接口,代表一个双端队列。包含一些栈方法。
ArrayDeque:基于数组实现的双端队列。可以当作栈来使用。

  1. LinkedList

是List接口的实现类,还实现了Deque接口。内部以链表的形式来保存集合中的元素。
提供了List的功能,还提供了双端队列和栈的功能。

Map集合

保存具有映射关系的数据,集合里面保存着两组值,一组用于保存key,另一组保存value,key和value都可以是任何引用类型的数据。key不允许重复。key集的存储形式和Set集合中元素的存储形式相似。Map提供了一个Entry内部类来封装key-value对,在计算Entry存储时只考虑Entry封装的key

  1. HashMap
    线程不安全的实现。允许使用null值作为key和value。
  2. Hashtable
    线程安全的Map实现。不允许使用null值作为key和value。

HashMap和Hashtable中用作key的对象必须实现hashCode()方法和equals()方法,并且这两个map集合也不能保证其中的key-value的顺序。1. 判断key值相等的标准:通过equals()方法返回true,hashCode值也相等。2. 判断两个value相等的标准:只要两个对象通过equals()方法比较返回true

  1. LinkedHashMap
    是HashMap的子类。使用双向链表来维护key-value对的次序,与插入顺序保持一致。
  2. Properties
    是Hashtable的子类。处理属性文件,将map对象和属性文件关联起来。相对于key,value都是String类型的Map。
  3. SortedMap接口和TreeMap实现类
    TreeMap是一个红黑树数据结构。key-value对作为红黑树的一个节点,在存储key-value对时,会根据key对节点进行排序
    自然排序
    定制排序·
  4. WeakHashMap
    key的类型是WeakRerfence,key被回收,key对应的指向的对象会被从Map容器中移除。
  5. IdentityHashMap
    实现机制与HashMap基本相似,但在处理两个key相等时:要求两个key严格相等时才认为两个key相等。
  6. EnumHashMap
    在内部以数组形式存储。不允许使用null作为key。
HashSet与HashMap

HashSet采用hash算法来决定集合中元素的存储位置,通过hash算法控制集合的大小。
HashMap类似HashSet,采用hash算法决定集合中key的存储位置,也通过hash算法来增加key集合的大小。

遍历集合
  1. Iterable接口的forEach()方法来遍历集合:传给该方法的参数是一个目标类型为Consumer类型的Lambda表达式。
  2. Iterator遍历集合元素:

Iterator对象是迭代器,必须依附于Collection对象。
Iterator遍历集合时,不是将集合元素本身传给了Iterator迭代变量,是将集合元素的值传给了迭代变量
Iterator迭代访问集合的元素时,集合里的元素不能被改变,否则会引发ConcurrentModificationException异常。只有使用Iterator的remove()方法删除上一次next()方法返回的集合元素才可以。

Iterator采用快速失败机制(fail-fast),在迭代过程中检测到集合元素已经被修改,立即引发ConcurrentModification异常。

快速失败机制(fail-fast)
对集合修改次数的期望值
对集合的修改次数:每次调用集合的add()方法或者remove()方法就会将该值加1或者减1。
修改次数的期望值刚刚开始时是等于修改次数的。

检查修改次数和修改次数的期望值是否相等,不等时抛出ConcurrentModificationException异常。

在Iterator的next()方法中,先会检查修改次数和修改次数的期望值是否相等,然后再得到集合里的下一个元素。

在Iterator实现类的remove()方法中,删除一个元素时,是调用集合自己的删除函数,并会将修改次数加一,并将修改次数的值赋值给修改次数的期望值
没有调用Iterator的remove()方法进行删除操作,使用集合的删除函数来进行删除操作时,修改次数会加1,但是不会将修改次数的值赋值为修改次数的期望值,导致修改次数的值和修改次数期望值的值不一致,在进行下一次next()迭代时,会检测出两者不相等,然后抛出ConcurrentModificationException异常。

单线程环境下:将使用集合进行删除操作修改为使用Iterator对象进行删除就会正确,不会抛出异常。
多线程环境下:就是使用Iterator的删除函数进行删除也还是会抛出异常。
因为在多线程环境下,每个线程是不同的Iterator对象,修改次数的期望值是线程私有的,修改次数是共享的。
当一个线程使用Iterator对象进行remove()删除时,这时候共享的修改次数值和这个线程的修改次数期望值都会自增;但是其他线程的私有的修改次数期望值没有自增,所以其他线程就会抛出ConcurrentModificationException异常了。

  1. Lambda表达式遍历:类似第一种。
  2. foreach循环遍历

迭代变量是集合元素的值,不是集合本身。
使用循环进行遍历时,也不能改变集合,否则会引发ConcurrentModificationException异常。

Hash算法

散列表
也叫哈希表,基于高速存取角度设计的,是以空间换时间,其中的元素不是紧密排列的,可能存在空隙。
以一种键-值(key-indexed)存储数据的结构,输入key,可查找到对应的值。

通过关键码值(key)直接进行访问存放记录(indexed值)的数组(散列表)。把关键码值通过映射函数(散列函数)映射到散列表中的一个位置来访问散列表中的记录
表中存储元素的位置称为

哈希表包含的属性
容量(capacity):表中桶的数量。
初始化容量:创建哈希表时桶的数量。
尺寸:当前哈希表中记录的数量。
负载因子:等于尺寸/容量
负载极限:是一个0-1的数值。默认的负载极限为0.75。决定了hash表的最大填满程度。当负载因子达到负载极限时,哈希表会自动成倍的增加桶的数量,并会将原有的对象重新分配,放入新的桶中。

hash冲突
两个元素通过映射函数得到的在散列表中的存储位置相同。
发生冲突的两个元素称为同义词

解决冲突
取决于3点:
a.散列函数,散列函数计算得到的表中的存储位置应平均分布。
b.处理冲突的方法。
c.负载因子的大小。
方法:
a.线性探测法:冲突后,线性向前探测,找到最近的一个空位置
b.双散列函数法:

CopyOnWriteArrayList
HashSet同步
LinkedHashSet的底层的链表

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

推荐阅读更多精彩内容