Java集合框架中隐藏的设计套路Word格式.docx
- 文档编号:21351600
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:12
- 大小:129.69KB
Java集合框架中隐藏的设计套路Word格式.docx
《Java集合框架中隐藏的设计套路Word格式.docx》由会员分享,可在线阅读,更多相关《Java集合框架中隐藏的设计套路Word格式.docx(12页珍藏版)》请在冰豆网上搜索。
小明说,设计思路?
为什么要了解,没时间啊,老夫写代码就是一把梭!
复制、粘贴,拿起键盘就是干!
效率刚刚的。
B大大心里一万只羊驼飞奔而过,嘴角抖了抖,说,那个小明,咱们今天的面试就先到这吧,有结果了我再让Hr通知你好吧。
然后,然后就没有然后了。
虽然这个故事是虚构的,但是不难找出来现实版的小明求职记。
那么从这个故事我们可以反思一些什么呢?
首先个人认为数据结构和算法、设计模式这些属于内功,俗话说练拳不练功,到老一场空,有了这些内功我们才能更好的去使用各种招式,否则只是徒有其形罢了。
要知道一个花架子是没有多少战斗力的。
其次,了解了源码里的设计思路,用起来才能更得心应手,同时也能提高自己的设计能力。
而且就像开篇说的,我们要善于从宏观的角度去看一些事情,这样才能看到更多,收获更多。
当然成长为高级工程师,迎娶白富美,走向人生巅峰不是梦啦。
数据结构和算法
这里我不打算再过多的重复数据结构和算法的定义、算法的时空复杂度这些问题,只过一下各个数据结构的特性。
因为算法对数据结构的通用操作类似,基本都包括插入、查找、删除、遍历和排序等,所以我们重点关注下这些操作上的性能。
数组:
优点是插入块,如果知道下标,可以非常快的存取。
缺点是查找慢,删除慢,大小固定。
有序数组:
优点是比无序数组查找快。
缺点是插入和删除慢,大小固定。
栈:
提供后进先出方式的存取。
缺点是存取其他项很慢。
队列:
提供先进先出方式的存取。
链表:
优点是插入快,删除快。
缺点是查找慢。
二叉树:
优点是查找、插入、删除都快(如果树保持平衡)。
缺点是删除算法复杂。
红-黑树:
优点是查找、插入、删除都快,树总是平衡的。
缺点是算法复杂。
2-3-4树:
优点是查找、插入、删除都快,树总是平衡的,类似的树对磁盘存储有用。
哈希表:
优点是如果关键字已知,则存取极快,插入快。
缺点是删除慢,如果不知道关键字则存取很慢,对存储空间使用不充分。
堆:
优点是插入、删除快,对最大数据项的存取很快。
缺点是对其他数据项存取慢。
图:
对现实世界建模。
有些算法慢且复杂。
Java中集合框架的总体设计
良好的设计总是相似的。
它使用一个好用的接口来封装一个特定的功能,它有效的使用CPU与内存,等等。
我们常用的数据结构有线性表、栈、队列等线性结构,还有集合以及哈希表,所以我们只讨论这几种结构的设计。
在分析Java集合框架的设计思路之前,我们先来认真思考一个问题,如果让你去设计Java的集合框架,你会怎么做?
小明的做法
如果是小明来设计的话,我猜他会选择一种简单粗暴的方式,分别去写几个类来实现线性表、栈、队列、集合以及哈希表。
好,那么问题来了。
假如用户想自定义一个用自己方式实现的线性表,那么他该如何操作?
假如开始用户使用了无序的线性表,然后因为某个需求要改成有序的,那么用户需不需要进行很大改动呢?
假如小明要对已有的Api进行升级,要加入无序线性表的另一种更高性能的实现,他需要改动多少东西?
其实把三个问题总结一下无非就是维护和扩展成本的问题。
我们的思路
首先我们先来参考一下其他功能的设计思路,比如Android中的View类族和Context类族。
我们分析一下他们的代码的结构层次。
View类族的类图如下
我们来分下一下这两个模块设计上相似的地方
整体的代码结构都像一棵树,有一个唯一的根节点,这个根节点封装了这个类族的公有特性
有一层抽象类或者类似抽象类作用的类,它们实现了通用的方法。
方便用户扩展自己的业务。
有具体的实现,用户可以直接使用这些具体实现。
这些相似的地方其实可以归纳为三个结构层次
一个高度抽象的根节点接口,可以再抽象出一组带有具体操作的接口来实现我们的根节点
一组抽象类,实现带有具体操作接口的部分方法,方便用户快速扩展自己的业务。
具体的实现,方便用户直接调用。
这个套路在Android源码中是很常见的,这样做的好处也显而易见,比较易于维护和扩展。
源码的实现思路
然后我们来看看是不是像我们说的那样,Java的集合框架也是这种套路呢?
我们来看下集合框架的类图
这张图是我从网上找的,不过不影响我们的分析。
如果有侵权,请告诉我,我会删除。
从这张图我们可以很清晰的看出来,套路一模一样有没有。
首先由于Map和Collection的相似点很少,所以这两部分的根节点是分开的。
我们拿Collection这部分来说,首先定义了一组接口。
Collection是List、Set等集合高度抽象出来的接口,它包含了这些集合的基本操作,它主要又分为:
List、Set和Queue,分别对应线性表、集合、队列,实现对应的接口,则有了对应数据结构的特性。
这是第一个结构层次。
然后又定义了一组抽象类,我们拿AbstractCollection类来说,先看下注释
/**
*Thisclassprovidesaskeletalimplementationofthe<
tt>
Collection<
/tt>
*interface,tominimizetheeffortrequiredtoimplementthisinterface.<
p>
*/
这个类实现了Collection接口的骨架,用户继承这个类可以用最小化的时间来实现一个集合。
其他的抽象类也都是各个数据结构的骨架,用户可以自定义自己的集合。
最后第三个层次就是具体的实现类了,比如我们常用的ArrayList、LinkedList等等。
比如LinkedList实现了List和Queue接口,那么它既有队列先进先出的特性,又有List可以通过位置访问元素的特性。
源码的具体实现
Collection部分
Collection是List、Set等集合高度抽象出来的接口,它包含了这些集合的基本操作,它主要又分为两大部分:
List和Set。
Collection接口
*Therootinterfaceinthe<
i>
collectionhierarchy<
/i>
.Acollection
*representsagroupofobjects,knownasits<
elements<
.Some
*collectionsallowduplicateelementsandothersdonot.Someareordered
*andothersunordered.TheJDKdoesnotprovideany<
direct<
*implementationsofthisinterface:
itprovidesimplementationsofmore
*specificsubinterfaceslike<
Set<
and<
List<
.Thisinterface
*istypicallyusedtopasscollectionsaroundandmanipulatethemwhere
*maximumgeneralityisdesired.
集合层次结构的根。
一个集合包含一组元素对象。
有一些集合允许重复元素,有一些不允许;
有一些集合元素是有序的有一些不是。
定义的方法:
intsize()
booleanisEmpty()
booleancontains(Objecto)
Iteratoriterator()
Object[]toArray()
T[]toArray(T[]a)
booleanadd(Ee)
booleanremove(Objecto)
booleancontainsAll(Collectionc)
booleanaddAll(Collectionc)
booleanremoveAll(Collectionc)
booleanretainAll(Collectionc)
voidclear()
Iterator接口
迭代器接口,用于遍历集合。
booleanhasNext()
Enext()
defaultvoidremove()
defaultvoidforEachRemaining(Consumeraction)
AbstractCollection抽象类
*
*Toimplementanunmodifiablecollection,theprogrammerneedsonlyto
*extendthisclassandprovideimplementationsforthe<
iterator<
and
*<
size<
methods.(Theiteratorreturnedbythe<
*methodmustimplement<
hasNext<
next<
.)<
*Toimplementamodifiablecollection,theprogrammermustadditionally
*overridethisclass'
s<
add<
method(whichotherwisethrowsan
UnsupportedOperationException<
),andtheiteratorreturnedbythe
methodmustadditionallyimplementits<
remove<
*method.<
*Theprogrammershouldgenerallyprovideavoid(noargument)and
constructor,aspertherecommendationinthe
interfacespecification.<
*Thedocumentationforeachnon-abstractmethodinthisclassdescribesits
*implementationindetail.Eachofthesemethodsmaybeoverriddenif
*thecollectionbeingimplementedadmitsamoreefficientimplementation.<
如果我们需要实现一个简单的集合,只需要重写iterator()、intsize()和add(Eo)方法。
同时这个集合的特性取决于我们的实现方式。
List接口
线性表(List):
零个或多个数据元素的有限序列。
*Anorderedcollection(alsoknownasa<
sequence<
).Theuserofthis
*interfacehasprecisecontroloverwhereinthelisteachelementis
*inserted.Theusercanaccesselementsbytheirintegerindex(positionin
*thelist),andsearchforelementsinthelist.<
一个有序的集合,用户可以通过这个接口精确的控制在哪里插入元素。
用户可以通过元素的int下标来拿到元素和查找List中的元素。
可以有重复元素。
List接口的扩展方法:
add(intindex,Eelement)
addAll(intindex,Collectionc)
Eget(intindex)
intindexOf(Objecto)
intlastIndexOf(Objecto)
ListIteratorlistIterator()
ListIteratorlistIterator(intindex)
Eremove(intindex)
defaultvoidreplaceAll(UnaryOperatoroperator)
Eset(intindex,Eelement)
defaultvoidsort(Comparatorc)
ListIterator接口
*Aniteratorforliststhatallowstheprogrammer
*totraversethelistineitherdirection,modify
*thelistduringiteration,andobtaintheiterator'
s
*currentpositioninthelist.A{@codeListIterator}
*hasnocurrentelement;
its<
I>
cursorposition<
/I>
always
*liesbetweentheelementthatwouldbereturnedbyacall
*to{@codeprevious()}andtheelementthatwouldbe
*returnedbyacallto{@codenext()}.
一个为List设计的迭代器,允许用户从任意方向遍历List,在遍历的过程中修改List,并且获得迭代器的当前位置。
ListIterator的扩展方法:
booleanhasPrevious()
Eprevious()
intnextIndex()
intpreviousIndex()
voidset(Ee)
voidadd(Ee)
Set接口
集合(Set):
是标记着具有某些相关联或相互依赖的一系列离散数据。
*Acollectionthatcontainsnoduplicateelements.Moreformally,sets
*containnopairofelements<
code>
e1<
/code>
e2<
suchthat
e1.equals(e2)<
andatmostonenullelement.Asimpliedby
*itsname,thisinterfacemodelsthemathematical<
set<
abstraction.
一个不包含重复元素的集合。
所谓不重复是指不能有两个元素e1.equals(e2),并且至多包含一个null元素。
Set接口只包含继承自Collection的方法,并增加了重复的元素被禁止约束性。
集还增加了对equals和hashCode操作的行为更强的契约,允许Set集合实例进行有意义的比较,即使他们的实现类型不同。
Queue
队列(Queue):
是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
*Acollectiondesignedforholdingelementspriortoprocessing.
*Besidesbasic{@linkjava.util.CollectionCollection}operations,
*queuesprovideadditionalinsertion,extraction,andinspection
*operations.Eachofthesemethodsexistsintwoforms:
onethrows
*anexceptioniftheoperationfails,theotherreturnsaspecial
*value(either{@codenull}or{@codefalse},dependingonthe
*operation).Thelatterformoftheinsertoperationisdesigned
*specificallyforewithcapacity-restricted{@codeQueue}
*implementations;
inmostimplementations,insertoperationscannot
*fail.
队列的接口,提供了Collection之外的插入、提取和检索操作。
这三种操作都有两种形式,一种失败之后会抛出异常,另一种会返回特定的值(null或者false)。
Map部分
Map是一个映射接口,其中的每个元素都是一个key-value键值对。
Map接口
散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。
对应关系f称为散列函数,又称为哈希(Hash)函数。
采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表或哈希表(Hashtable)。
*Anobjectthatmapskeystovalues.Amapcannotcontainduplicatekeys;
*eachkeycanmaptoatmostonevalue.
一个匹配key和value的对象。
包含的主要方法:
booleancontainsKey(Objectkey)
booleancontainsValue(Objectvalue)
Vget(Objectkey)
Vput(Kkey,Vvalue)
Vremove(Objectkey)
putAll(Mapm)
clear()
SetkeySet()
Collectionvalues()
entrySet()
booleanequals(Objecto)
inthashCode()
Map接口中包含一个Entry接口,这是对Map一个条目的封装即一个键值对。
可以通过它操作条目的键值。
AbstractMap
实现Map接口的骨架,减小用户创建自定义Map的成本。
如果你想创建一个自己的可以修改的Map,比如重写Vput(Kkey,Vvalue)和Vremove(Objectkey)方法以及实现entrySet().iterator()。
SortedMap接口
*A{@linkMap}thatfurtherprovidesa<
em>
totalordering<
/em>
onitskeys.
*Themapisorderedaccordingtothe{@linkplainComparablenatural
*ordering}ofitskeys,orbya{@linkComparator}typically
*providedatsortedmapcreationtime.Thisorderisreflectedwhen
*iteratingoverthesortedmap'
scollectionviews(returnedbythe
*{@codeentrySet},{@codekeySet}and{@codevalues}methods).
*Severaladditionaloperationsareprovidedtotakeadvantageofthe
*ordering.(Thisinterfaceisthemapanalogueof{@linkSortedSet}.)
提供了进一步对Map的key进行排序的操作。
扩展的方法:
Comparatorcomparator()
KfirstKey()
KlastKey()
SortedMapheadMap(Kt
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 集合 框架 隐藏 设计 套路