java基础之集合略解

Java集合:整体结构

HashMap剖析

Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例

集合类结构

Java中的集合包含多种数据结构,如链表、队列、哈希表等。从类的继承结构来说,可以分为两大类,一类是继承自Collection接口,这类集合包含List、Set和Queue等集合类。另一类是继承自Map接口,这主要包含了哈希表相关的集合类。下面我们看一下这两大类的继承结构图:

1、List、Set和Queue


2、Map:

图中的绿色的虚线代表实现,绿色实线代表接口之间的继承,蓝色实线代表类之间的继承。

List

(1)List:我们用的比较多List包括ArrayListLinkedList,这两者的区别也很明显,从其名称上就可以看出。ArrayList的底层的通过数组实现,所以其随机访问的速度比较快,但是对于需要频繁的增删的情况,效率就比较低了。而对于LinkedList,底层通过链表来实现,所以增删操作比较容易完成,但是对于随机访问的效率比较低。

至于Vector,它是ArrayList的线程安全版本,而Stack则对应栈数据结构。

Queue

(2)Queue:一般可以直接使用LinkedList完成,从上述类图也可以看出,LinkedList继承自Deque(双端队列),所以LinkedList具有双端队列的功能。PriorityQueue的特点是为每个元素提供一个优先级,优先级高的元素会优先出队列。

Set

Set与List的主要区别是Set是不允许元素重复的,且存取是无序的(存入和取出不按照顺序),而List则可以允许元素重复的且存取有序。判断元素的重复需要根据对象的hash方法和equals方法来决定。这也是我们通常要为集合中的元素类重写hashCode方法和equals方法的原因。

HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。 

TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。 

LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。

Map

Map类型的集合最大的优点在于其查找效率比较高,理想情况下可以实现O(1)的时间复杂度。

Map中最常用的是HashMapLinkedHashMap与HashMap的区别在于前者能够保证插入集合的元素顺序与输出顺序一致。

HashMapTreeMap的区别,与之前提到的HashSet与TreeSet的区别是一致的

HashSet和TreeSet本质上分别是通过HashMap和TreeMap来实现的



TreeSet和TreeMap存储原理

TreeSet:按特定顺序存放元素,底层结构是红黑二叉树。

红黑树算法的规则: 左小右大。

既然TreeSet可以自然排序,那么TreeSet必定是有排序规则的。

1:让存入的元素自定义比较规则。

元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。

2:给TreeSet指定排序规则。

当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。

注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;

当compareTo()函数返回值为0时,说明两个对象相等,此时该对象不会添加进来。

为什么使用TreeSet存入字符串,字符串默认输出是按升序排列的?

因为字符串实现了一个接口,叫做Comparable 接口.字符串重写了该接口的compareTo 方法,所以String对象具备了比较性.那么同样道理,我的自定义元素(例如Person类,Book类)想要存入TreeSet集合,就需要实现该接口,也就是要让自定义对象具备比较性.



TreeMap:TreeMap根据集合中的键进行排序

方式一:元素自身具备比较性

和TreeSet一样原理,需要让存储在位置的对象实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。

方式二:容器具备比较性

当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。

当key比较相同时,value会覆盖之前的value。



HashSet和HashMap存储原理

HashSet:元素加入Set之前需要先执行hashCode方法,如果返回的值在集合中已存在,则要继续执行equals方法,如果equals方法返回的结果也为真,则证明该元素已经存在,会将新的元素覆盖老的元素,如果返回hashCode值不同,则直接加入集合。



HashMap:

结构图

1.HashMap是一个数组+链表的结构,数组的下标在HashMap中称为Bucket(水桶)值,每个数组项对应的是一个List(单向链表)

2.每个List中存放的是Entry对象,这个Entry对象包含键和值以及下一个Entry的地址。(其实就是数组中存放的是Entry对象,而Entry对象实际上是一个单向链表)。

存储过程:

1.通过key的hashCode()函数计算key的hash值,再通过hash值得出Bucket值(如何通过hash值的出Bucket值,哈希值 % 数组容量 = bucketIndex )

2.得出Bucket值后,如果该Bucket值对应的list是一个空列表,那么将生成entry对象,插入到list中,做为list的第一个元素

3.如果该Bucket值对应的list中已经有其它对象了(如果两个key的hash值一样就会发生),这个时候就发生了碰撞。

4.发生了碰撞后,新插入的key就会和链表中的其它entry的key进行比较,比较过程需要用到equals()方法

如果两个key的hashcode一样,并且equals方法比较也相同,那么HashMap就判断这两个key完全一样

5.如果两个key比较结果一样,由于HashMap不允许同时存在两个相同的key,那么新插入的entry就会覆盖旧entry

6.如果比较不一样,那么将新的entry插入到list的末尾


那么在这里,Entry<K,V>是Map的内部接口,HashMap中的内部类Node<K,V>(JDK1.8以前是Entry)实现了Map.Entry,HashMap内部通过Node数组存储数据。所以若要遍历HashMap,可获取entrySet再遍历。

transient Node[] table;

HashMap为何如此设计

HashMap中的数据结构是数组+单链表的组合,我们希望的是元素存放的更均匀,最理想的效果是,Entry数组中每个位置都只有一个元素,这样,查询的时候效率最高,不需要遍历单链表,也不需要通过equals去比较Key,而且空间利用率最大。那么怎么才能将分布最大的均匀化呢?那就是取余运算%,哈希值 % 数组容量 = bucketIndex

JDK1.8的修改

在JDK1.6中,HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的节点都存储在一个链表里。但是当位于一个链表中的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,HashMap采用数组+链表+红黑树来实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

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

推荐阅读更多精彩内容

  • Java集合类可用于存储数量不等的对象,并可以实现常用的数据结构如栈,队列等,Java集合还可以用于保存具有映射关...
    小徐andorid阅读 1,915评论 0 13
  • 一、集合入门总结 集合框架: Java中的集合框架大类可分为Collection和Map;两者的区别: 1、Col...
    程序员欧阳阅读 11,525评论 2 61
  • Java集合框架 Java中封装了许多常用的数据结构,称为集合框架,可以有效组织数据,提高程序性能。最初Java只...
    Steven1997阅读 906评论 0 2
  • 參加了3天的中國式眾籌學習,聽楊勇老師說終極的眾籌是人才IPO,很認同他眾籌改變一切的提法。昨天和4個同學頭腦風暴...
    京公民冉启发阅读 171评论 0 0
  • 有多少的婚姻,是从充满浪漫的美好爱情开始,慢慢都变成为了孩子凑合着过完一生。。。。。。
    风吹过田野007阅读 180评论 0 0