gzdjava集合框架的一些源码类型分析Word文档格式.docx
- 文档编号:22254411
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:14
- 大小:3.01MB
gzdjava集合框架的一些源码类型分析Word文档格式.docx
《gzdjava集合框架的一些源码类型分析Word文档格式.docx》由会员分享,可在线阅读,更多相关《gzdjava集合框架的一些源码类型分析Word文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
除了四个历史集合类外,Java2框架还引入了六个集合实现,如下表所示。
接口
实现
历史集合类
Set
HashSet
TreeSet
List
ArrayList
Vector
LinkedList
Stack
Map
HashMap
Hashtable
TreeMap
Properties
集合详解之collection
collevction的实现基础是Object数组,所以他肯定有toArray方法
任何容器,都能将元素放进去、取出来,而且collection没有get()方法,要想从中去除元素,只有遍历了,所以Collection接口提供了iterator方法,此方法返回一个iterator对象,利用iterator接口的接口的方法,对Collection进行遍历。
而iterator接口的方法很少,只有booleanhasNext();
Enext();
voidremove();
。
集合详解之List
List接口只继承了Collection接口
两种常对List接口的实现
简述
操作特性
成员要求
提供基于索引的对成员的随机访问
提供快速基于索引的成员访问,对头尾的增加删除等最好
任意Object自雷的对象
对任何位置的增加删除支持特别好,但是基于索引的成员访问功能差
任意Object子类的对象
ArrayList简单分析实现原理
ArrayList的3个构造函数
这个构造函数比较重要,但是不常用。
其中intinitialCapacity表示构造这个ArrayList初始列表的容量,理解这个参数的方式得看ArrayList的两个属性,第一个属性
,我们使用elementData[]这个数组来存放集合中的数据,而intinitialCapacity就是这个数组的lengh!
默认值为10!
下面说第二个属性
size表示列表中真是数据的存放个数!
这个构造函数的作用就是把另一个容器对象中的元素放到当前List对象中去!
ElementData[]被容器CtoArray后赋值,然后ArrayList的实际尺寸Size为此时的ElecmentData[]的长度,然后利用elementData[],ArrayList的尺寸Size,和获取的class来创建一个ArrayList!
!
疑问?
?
既然ArrayList是基于数组来实现的,那么elementData[]数组的长度是固定的,而怎么能通过Size来最后确定ArrayList尺寸?
既然这样,那就是elementData[]有它的扩容机制!
先说ArrayList是继承了抽象类AbstractList而在这个抽象类中有modcount的变量
并且被初始化为0,这个变量表示对elementData数组进行了多少次操作,比如扩容、清空。
再看源码
首先得到当前elementData 属性的长度oldCapacity。
然后通过判断oldCapacity和mi-nCapacity参数谁大来决定是否需要扩容
如果minCapacity大于oldCapacity,那么我们就对当前的List对象进行扩容。
扩容的的策略为:
取(oldCapacity*3)/2+1和minCapacity之间更大的那个。
然后使用数组拷贝的方法,把以前存放的数据转移到新的数组对象中
如果minCapacity不大于oldCapacity那么就不进行扩容。
集合讲解之Map
Map简单原理
从图中可以知道,他和collection没有一点关系!
下面为Map几种常用实现类的比较
保存键值对成员,基于键找值操作,使用compareTo或compare方法对键进行排序
能满足用户对Map的通用需求
键成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。
支持对键有序地遍历,使用时建议先用HashMap增加和删除成员,最后从HashMap生成TreeMap;
附加实现了SortedMap接口,支持子Map等要求顺序的操作
键成员要求实现Comparable接口,或者使用Comparator构造TreeMap键成员一般为同一类型。
LinkedHashMap
保留键的插入顺序,用equals方法检查键和值的相等性
成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。
注意:
treeMap是通过key来排序的,所以要求Key对象要实现Comparable接口!
HashMap的实现原理
Hash算法和Hash表
Hash算法的意义在于提供了一种快速存取数据的方法,它用一种算法建立键值与真实值之间的对应关系,(每一个真实值只能有一个键值,但是一个键值可以对应多个真实值),这样可以快速在数组等里面存取数据。
HashMap属性1
用来存放键值对的对象Entry数组,也就是Hash表
在Map接口中有内部接口
,用它来保存我们的键值对!
HashMap属性2
当前Map中存放的键值对的个数
HashMap属性3
负载因子,用来决定什么情况下应该对Entry进行扩容
主要构造函数
1.
首先是判断参数intinitialCapacity和floatloadFactor是否合法
2.
然后确定Hash表的初始化长度。
确定的策略是:
通过传进来的参数initialCapacity来找出第一个大于它的2的次方的数。
比如说我们传了18这样的一个initialCapacity参数,那么真实的table数组的长度为2的5次方,即32。
之所以采用这种策略来构建Hash表的长度,是因为2的次方的运算对于现代的处理器来说,可以通过一些方法得到更加好的执行效率。
3.
接下来就是得到重构因子(threshold)了,这个属性也是HashMap中的一个比较重要的属性,它表示,当Hash表中的元素被存放了多少个之后,我们就需要对该Hash表进行重构。
4.
最后就是使用得到的初始化参数capacity来构建Hash表:
Entry[]table。
如何添加键值对
首先我们判断如果key为null则使用一个常量来代替该key值,该行为在方法maskNull()终将key替换为一个非null的对象k。
计算key值的Hash码:
hash
通过使用Hash码来定位,我们应该把当前的键值对存放到Hash表中的哪个格子中。
indexFor()方法计算出的结果:
i就是Hash表(table)中的下标。
然后遍历当前的Hash表中table[i]格中的链表。
从中判断已否已经存在一样的键(Key)的键值对。
如果存在一样的key的键,那么就用新的value覆写老的value,并把老的value返回
5.
如果遍历后发现没有存在同样的键值对,那么就增加当前键值对到Hash表中的第i个格子中的链表中。
并返回null。
最后我们看看一个键值对是如何添加到各个格子中的链表中的:
我们先看voidaddEntry(inthash,Objectkey,Objectvalue,intbucketIndex)方法,该方法的作用就用来添加一个键值对到Hash表的第bucketIndex个格子中的链表中去。
这个方法作的工作就是:
创建一个Entry对象用来存放键值对。
添加该键值对----Entry对象到链表中
最后在size属性加一,并判断是否需要对当前的Hash表进行重构。
如果需要就在voidresize(intnewCapacity)方法中进行重构。
之所以需要重构,也是基于性能考虑。
大家可以考虑这样一种情况,假定我们的Hash表只有4个格子,那么我们所有的数据都是放到这4个格子中。
如果存储的数据量比较大的话,例如100。
这个时候,我们就会发现,在这个Hash表中的4个格子存放的4个长长的链表。
而我们每次查找元素的时候,其实相当于就是遍历链表了。
这种情况下,我们用这个Hash表来存取数据的性能实际上和使用链表差不多了。
但是如果我们对这个Hash表进行重构,换为使用Hash表长度为200的表来存储这100个数据,那么平均2个格子里面才会存放一个数据。
这个时候我们查找的数据的速度就会非常的快。
因为基本上每个格子中存放的链表都不会很长,所以我们遍历链表的次数也就很少,这样也就加快了查找速度。
但是这个时候又存在了另外的一个问题。
我们使用了至少200个数据的空间来存放100个数据,这样就造成至少100个数据空间的浪费。
在速度和空间上面,我们需要找到一个适合自己的中间值。
在HashMap中我们通过负载因子(loadFactor)来决定应该什么时候应该重构我们的Hash表,以达到比较好的性能状态。
集合之Set
Set
成员不能重复
外部无序地遍历成员。
外部有序地遍历成员;
附加实现了SortedSet,支持子集等要求顺序的操作
成员要求实现Comparable接口,或者使用Comparator构造TreeSet。
成员一般为同一类型。
LinkedHashSet
外部按成员的插入顺序遍历成员
成员与HashSet成员类似
Java中Set的概念和数学中的集合(set)一致,都表示一个集内可以存放的元素是不能重复的。
前面我们会发现,Set中很多实现类和Map中的一些实现类的使用上非常的相似。
而且前面再讲解Map的时候,我们也提到:
Map中的“键值对”,其中的“键”是不能重复的。
这个和Set中的元素不能重复一致。
我们以HashSet为例来分析一下,会发现其实Set利用的就是Map中“键”不能重复的特性来实现的。
先看看HashSet中的有哪些属性:
再结合构造函数来看看:
通过这些方法,我们可以发现,其实HashSet的实现,全部的操作都是基于HashMap来进行的。
我们看看是如何通过HashMap来保证我们的HashSet的元素不重复性的:
看到这个操作我们可以发现HashSet的巧妙实现:
就是建立一个“键值对”,“键”就是我们要存入的对象,“值”则是一个常量。
这样可以确保,我们所需要的存储的信息之是“键”。
而“键”在Map中是不能重复的,这就保证了我们存入Set中的所有的元素都不重复。
而判断是否添加元素成功,则是通过判断我们向Map中存入的“键值对”是否已经存在,如果存在的话,那么返回值肯定是常量:
PRESENT,表示添加失败。
如果不存在,返回值就为null表示添加成功。
我们再看看其他的方法实现:
了解了这些后,我们就不难理解,为什么HashMap中需要注意的地方,在HashSet中也同样的需要注意。
其他的Set的实现类也是差不多的原理。
至此对于Set我们就应该能够比较好的理解了。
总结:
集合框架中常用类比较
用“集合框架”设计软件时,记住该框架四个基本接口的下列层次结构关系会有用处:
Collection接口是一组允许重复的对象。
Set接口继承Collection,但不允许重复。
List接口继承Collection,允许重复,并引入位置下标。
Map接口既不继承Set也不继承Collection,存取的是键值对
我们以下面这个图表来描述一下常用的集合的实现类之间的区别:
Collection/Map
成员重复性
元素存放顺序(Ordered/Sorted)
元素中被调用的方法
基于那中数据结构来实现的
Uniqueelements
Noorder
equals()
hashCode()
Hash表
Insertionorder
Hash表和双向链表
SortedSet
Sorted
compareTo()
平衡树(Balancedtree)
Allowed
数组
链表
Uniquekeys
Keyinsertionorder/Accessorderofentries
SortedMap
Sortedinkeyorder
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- gzdjava 集合 框架 一些 源码 类型 分析