2019/7/1 二刷結(jié)束留念
mark:重寫(xiě)equals和hashCode方法的情景~
????01-集合框架(體系概述)
? ? ? ? 為什么會(huì)出現(xiàn)集合類(lèi)呢儿咱?? ? ? ??
? ? ? ? 面向?qū)ο笳Z(yǔ)言對(duì)事物的體現(xiàn)都是以對(duì)象的形式,所以為了方便對(duì)多個(gè)對(duì)象的操作牢撼,就對(duì)對(duì)象進(jìn)行存儲(chǔ),集合就是存儲(chǔ)對(duì)象最常用的一種方式满葛。
? ? ? ? 那存到哪里去捏?
? ? ? ? 有兩種存儲(chǔ)的地方可以用医男,第一種是數(shù)組滑绒,第二種是集合。
? ? ? ? 對(duì)象多了用集合存骚勘,數(shù)據(jù)多了用對(duì)象存铐伴,像姓名年齡這些都是數(shù)據(jù)~
? ? ? ? 可是已經(jīng)有數(shù)組啦,為什么還要有集合呢调鲸?
? ? ? ? 數(shù)組是固定長(zhǎng)度的盛杰,集合是可變長(zhǎng)度的。
? ? ? ? 而且藐石,數(shù)組當(dāng)中存儲(chǔ)對(duì)象的時(shí)候即供,它只能存儲(chǔ)同一種類(lèi)型的對(duì)象,比如說(shuō)全存Demo或者全存Person于微,因?yàn)閿?shù)組定義的時(shí)候已經(jīng)指定了數(shù)據(jù)類(lèi)型啦逗嫡。
? ? ? ? 而集合不是,對(duì)它來(lái)說(shuō)只要是對(duì)象就行株依。先存一個(gè)new Person()進(jìn)去驱证,再存一個(gè)new Demo()進(jìn)去,都沒(méi)問(wèn)題噠恋腕。
? ? ? ? 所以抹锄,集合的特點(diǎn)是:集合的長(zhǎng)度是可變的,集合可以存儲(chǔ)不同類(lèi)型的對(duì)象。
? ? ? ? 集合作為一種容器伙单,也劃分成了很多種获高。對(duì)它們不斷的進(jìn)行共性抽取,就形成了一個(gè)體系吻育,我們叫做集合框架念秧。
? ? ? ? 嘿嘿,這個(gè)圖看著理解一下:
? ? ? ? 這個(gè)體系里面包含很多內(nèi)容布疼。
? ? ? ? 框架產(chǎn)生之后摊趾,我們一般會(huì)先看什么呢?
? ? ? ? 是不是會(huì)先看頂層呀~因?yàn)轫攲赢?dāng)中定義的是這個(gè)體系當(dāng)中最共性、最基本的行為游两,把這個(gè)頂層看明白之后砾层,這個(gè)體系的基本功能就了解了。
? ? ? ? 看完了頂層之后器罐,找底層來(lái)用~
? ? ? ? 為什么呢梢为?
? ? ? ? 有兩點(diǎn)原因:
? ? ? ? 1,不斷向上抽取出來(lái)的東西很有可能是不能創(chuàng)建對(duì)象的轰坊,它可能是抽象的铸董。
? ? ? ? 2,創(chuàng)建子類(lèi)對(duì)象肴沫,方法更多一些粟害。
? ? ? ? 所以說(shuō),參閱頂層颤芬,創(chuàng)建底層悲幅。
? ? ? ? 而這個(gè)頂層,就叫Collection站蝠,收集汰具、集合的意思。
? ? ? ? 集合框架是工具包中的一個(gè)成員菱魔,它在java.util這個(gè)包中留荔。
? ? ? ? Collection是一個(gè)接口。在不斷向上抽取的過(guò)程中澜倦,全變成抽象辣~它有很多實(shí)現(xiàn)類(lèi)聚蝶,也有很多子接口。
? ? ? ? 因?yàn)樽咏涌谔嘣逯危筒话€(gè)講啦碘勉。重點(diǎn)講兩個(gè):List和Set。
? ? ? ? 把剛剛那個(gè)示意圖簡(jiǎn)單填充了一下:
? ? ? ? 這些就是我們要重點(diǎn)講的內(nèi)容桩卵。
? ? ? ? 那么問(wèn)題來(lái)啦验靡,為什么要出現(xiàn)這么多種容器呢倍宾?
? ? ? ? 因?yàn)槊恳粋€(gè)容器對(duì)數(shù)據(jù)的存儲(chǔ)方式都有不同。
? ? ? ? 這個(gè)存儲(chǔ)方式稱(chēng)之為:數(shù)據(jù)結(jié)構(gòu)晴叨。
????02-集合框架(共性方法)
? ? ? ? 我們先從Collection開(kāi)始學(xué)起~
? ? ? ? Colletion是Colletion層次結(jié)構(gòu)中的跟接口凿宾。
????????方法摘要:
? ? ? ? 在上述方法中矾屯,我們發(fā)現(xiàn)了一些不清楚的數(shù)據(jù)類(lèi)型:
? ? ? ? 我們看到的這些不懂的字母兼蕊,就先把它們理解成Object類(lèi)~
? ? ? ? 頂層方法看完該建立子類(lèi)對(duì)象啦,我們先建立ArrayList對(duì)象吧~
? ? ? ? add方法的參數(shù)類(lèi)型是Object件蚕,以便于接收任意類(lèi)型對(duì)象孙技。
? ? ? ? 集合中存儲(chǔ)的都是對(duì)象的引用(地址)。就像這樣排作,簡(jiǎn)單示意圖:
? ? ? ? ?打印集合對(duì)象:
? ? ? ? 刪除元素:
????????運(yùn)行結(jié)果:
? ? ? ? 寫(xiě)這句就全刪啦(這個(gè)叫清空集合):
? ? ? ? 判斷元素:?
? ? ? ? 取交集:
? ? ? ? 取交集牵啦,al1中只會(huì)保留和al2中相同的元素~
? ? ? ? 再試試removeAll,是將和al2中相同的元素刪掉~(yú)
????03-集合框架(迭代器)
? ? ? ? 在Collection中妄痪,有一個(gè)方法叫iterator:
? ? ? ? 它是一個(gè)接口誒:
? ? ? ? 這個(gè)接口中有三個(gè)方法:
? ? ? ? 試著用一下:
? ? ? ? Iterator it=al.iterator();//獲取迭代器哈雏,用于取出集合中的元素。
????????我們發(fā)現(xiàn)它將集合中的前兩個(gè)元素拿出來(lái)啦衫生。
????????但是如果這個(gè)集合中元素很多裳瘪,這樣一個(gè)一個(gè)寫(xiě)就太麻煩了。
? ? ? ? 我們有更方便的方法呢:
? ? ? ? 那么什么是迭代器呢罪针?
? ? ? ? 其實(shí)就是集合的取出元素的方式彭羹。
? ? ? ? 對(duì)于取出這個(gè)動(dòng)作,一個(gè)函數(shù)不能完全描述泪酱,需要用多個(gè)功能來(lái)體現(xiàn)派殷,這種情況下,就需要將功能們封裝到一個(gè)對(duì)象中去墓阀。
? ? ? ? 畫(huà)個(gè)圖解釋一下迭代器的特點(diǎn)毡惜,這里有三種容器,每個(gè)容器中都有一個(gè)取出的對(duì)象:
? ? ? ? 而且斯撮,因?yàn)閿?shù)據(jù)結(jié)構(gòu)的不同经伙,每個(gè)取出對(duì)象中的實(shí)現(xiàn)方式也不一樣。
? ? ? ? 那么吮成,這個(gè)取出就需要被描述一下橱乱,怎么描述呢?
? ? ? ? 通過(guò)一個(gè)類(lèi)來(lái)完成粱甫,而這個(gè)類(lèi)泳叠,就定義在了集合的內(nèi)部。
? ? ? ? 為什么定義在集合內(nèi)部呢茶宵?
? ? ? ? 因?yàn)樵鼐驮诩蟽?nèi)部危纫,如果想要操作這些元素,是不是集合的內(nèi)部類(lèi)最方便啦。
? ? ? ? 一般取出分為兩步:1种蝶,判斷元素是否存在2契耿,若存在則取出。
? ? ? ? 根據(jù)容器數(shù)據(jù)結(jié)構(gòu)的不同螃征,每個(gè)容器判斷和取出的具體實(shí)現(xiàn)細(xì)節(jié)不一樣搪桂。但是它們都是有共性?xún)?nèi)容:判斷和取出,那么可以將共性抽取盯滚,形成一個(gè)接口踢械,這個(gè)接口就是Iterator:
? ? ? ? 這些內(nèi)部類(lèi)都符合一個(gè)規(guī)則,該規(guī)則就是Iterator魄藕。
? ? ? ? 如何獲取集合的取出對(duì)象呢内列?
? ? ? ? 通過(guò)一個(gè)對(duì)外提供的方法:iterator();
? ? ? ? 這個(gè)對(duì)外提供的方法就相當(dāng)于娃娃機(jī)外面的操縱桿背率,而夾子就相當(dāng)于迭代器话瞧,它是封裝在娃娃機(jī)里面的,可以取出娃娃寝姿,只對(duì)外暴露了操縱桿這個(gè)方法交排,可以讓人使用。不同的娃娃機(jī)会油,它們的夾子也不一樣个粱,有兩個(gè)鉤的,有五個(gè)鉤的翻翩,實(shí)現(xiàn)方法都不一樣都许,但它們都是夾子~
? ? ? ? 后面我們?cè)俣x新的容器,只要將它的取出方法實(shí)現(xiàn)Iterator接口就可以啦:
? ? ? ? 取出方式就這樣被統(tǒng)一啦嫂冻,再新加集合也不怕~
? ? ? ? 除了用while循環(huán)胶征,它也可以用for循環(huán)寫(xiě):
? ? ? ? 這兩種循環(huán)有什么不同呢?
? ? ? ? 推薦用for循環(huán)桨仿,因?yàn)閒or循環(huán)結(jié)束后睛低,it就釋放了,不再占用內(nèi)存空間服傍,而while循環(huán)的話(huà)則依然占用內(nèi)存空間钱雷。
????04-集合框架(List集合共性方法)
Collection
? ? ? ? |——List:元素是有序的,元素可以重復(fù)吹零,因?yàn)樵摷象w系有索引罩抗。
? ? ? ? |——Set:元素是無(wú)序,元素不可以重復(fù)灿椅,該集合當(dāng)中沒(méi)有索引套蒂。
????????我們先講List钞支。
? ? ? ? 我們?nèi)ist類(lèi)中看一看它的方法~共性方法就不說(shuō)啦,它的特有方法有:
? ? ? ? 在指定位置插入指定元素:
? ? ? ? 通過(guò)索引獲取元素:
? ? ? ? 獲取元素的索引:
? ? ? ? List集合特有的迭代器:
? ? ? ? 移除指定元素:
? ? ? ? 改變指定位置的元素:
? ? ? ? 獲取指定區(qū)間元素(包含頭不包含尾):
? ? ? ? 綜上操刀,凡是可以操作角標(biāo)的方法都是List體系特有的方法烁挟。
? ? ? ? 總結(jié)一下:
? ? ? ? 接下來(lái)挨個(gè)演示一遍。
? ? ? ? 在指定位置添加元素:
? ? ? ? 刪除指定位置的元素:
? ? ? ? 修改元素:
? ? ? ? 通過(guò)角標(biāo)獲取元素:
? ? ? ? 獲取所有元素:
? ? ? ? 如上骨坑,List集合有自己特殊的取值方式撼嗓,就是遍歷。
? ? ? ? 我們用迭代器也可以實(shí)現(xiàn)這個(gè)功能:
????05-集合框架(ListIterator)
? ? ? ? 通過(guò)indexOf獲取對(duì)象的位置卡啰、獲取指定區(qū)間的元素:? ? ? ? ?
? ? ? ? 接下來(lái)看一下列表迭代器listIterator静稻。
? ? ? ? 它和普通迭代器到底有什么不同呢?
? ? ? ? 看示例:?
? ? ? ? 程序運(yùn)行過(guò)程中掛掉了:
? ? ? ? 我們來(lái)看一下這個(gè)異常:
? ? ? ? 我們來(lái)分析一下:
? ? ? ? 所以就存在安全隱患啦匈辱。不能同時(shí)用多種方式操作同一種元素,否則可能會(huì)發(fā)生并發(fā)修改異常杀迹。
? ? ? ? 那該怎么解決呢亡脸?
? ? ? ? 要么全用集合的方法,要么全用迭代器的方法树酪。
? ? ? ? 全用迭代器的方法:
? ? ? ? java02不是被刪除了嗎浅碾?為什么籃框部分還被打印了呢?
? ? ? ? 因?yàn)殡m然這個(gè)元素的引用被移除了续语,可是在移除前它還被obj使用了垂谢,后面打印的是obj~
? ? ? ? 注意,剛剛用的都是迭代器的操作疮茄,做了判斷滥朱、取出和移除,迭代器只能做這三個(gè)動(dòng)作力试,添加和修改動(dòng)作它做不了徙邻,有局限性。
? ? ? ? 不要怕~
? ? ? ? 它也知道自己有局限性畸裳,所以安排了一個(gè)小弟:
? ? ? ? 列表迭代器ListIterator有指針缰犁,有角標(biāo),所以它的方法比它的爸爸Iterator多多啦:
? ? ? ? 增刪查改樣樣都可以呢怖糊。
? ? ? ? List集合特有的迭代器:ListIterator是Iterator的子接口帅容。
? ? ? ? 我們用一下~?
? ? ? ? 添加:
? ? ? ? 修改:
? ? ? ? 除了hasNext,它還有hasPrevious:
? ? ? ? 試一下~?
? ? ? ? 我們反向取一次:
? ? ? ? 實(shí)際開(kāi)發(fā)中逆向遍歷用的少一些伍伤,正向遍歷用的多一些并徘。
? ? ? ? ListIterator出現(xiàn)后,可以對(duì)集合進(jìn)行在遍歷過(guò)程中的增刪改查嚷缭。
????06-集合框架(List集合具體對(duì)象的特點(diǎn))
????????Colletion中List集合的共性方法說(shuō)完以后饮亏,介紹一下List集合中常見(jiàn)的三個(gè)子類(lèi)對(duì)象: ArrayList耍贾、LinkedList、Vetor路幸。
? ? ? ? 這三個(gè)子類(lèi)對(duì)象的出現(xiàn)荐开,是因?yàn)榈讓拥臄?shù)據(jù)結(jié)構(gòu)不一樣而出現(xiàn)的,那么它們的底層到底是什么樣的數(shù)據(jù)結(jié)構(gòu)呢简肴?換句話(huà)說(shuō)晃听,它們的底層到底是怎樣對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ)的呢?
? ? ? ? ArrayList:底層的數(shù)據(jù)結(jié)構(gòu)使用的是數(shù)組結(jié)構(gòu)砰识。特點(diǎn):查詢(xún)速度快能扒。但是增刪稍慢(元素不多還好,多了之后慢得就比較明顯)辫狼。線(xiàn)程不同步初斑。
? ? ? ? LinkedList:底層使用的鏈表數(shù)據(jù)結(jié)構(gòu)。特點(diǎn):增刪速度很快膨处,查詢(xún)稍慢见秤。
? ? ? ? Vector:底層是數(shù)組數(shù)據(jù)結(jié)構(gòu)。線(xiàn)程同步真椿。(它1.0就出現(xiàn)了鹃答,那個(gè)時(shí)候還木有集合框架呢,而ArrayList是1.2出現(xiàn)的)被ArrayList替代了突硝。
? ? ? ? ArrayList和Vector中测摔,建議用ArrayList,因?yàn)樾矢呓馇。瑹o(wú)論增刪還是查詢(xún)锋八,Vector都稍慢。
? ? ? ? 那多線(xiàn)程怎么辦吶修噪?
? ? ? ? 可以自己加鎖~
? ? ? ? 那我自己加鎖不安全怎么辦呢查库?
? ? ? ? 就怕你不會(huì)加所以Java的集合框架中提供了另外一個(gè)功能,專(zhuān)門(mén)幫助小笨笨來(lái)加鎖的~
? ? ? ? 怎么加呢黄琼?“把你的不安全的給我樊销,我給你個(gè)安全的≡嗫睿”好霸道總裁围苫。。撤师。
? ? ? ? 還有一個(gè)小問(wèn)題~ArrayList和Vector都是數(shù)組數(shù)據(jù)結(jié)構(gòu)剂府,而數(shù)組數(shù)據(jù)結(jié)構(gòu)的特點(diǎn)是它的長(zhǎng)度是固定的,集合卻是可變長(zhǎng)度的剃盾,所以ArrayList和Vector是可變長(zhǎng)度的數(shù)組腺占。什么叫可變長(zhǎng)度的數(shù)組呢淤袜?
? ? ? ? ArrayList默認(rèn)的長(zhǎng)度是10:
? ? ? ? 當(dāng)長(zhǎng)度超過(guò)之后,它會(huì)new一個(gè)新的數(shù)組衰伯,長(zhǎng)度是多少呢铡羡?50%延長(zhǎng),變15意鲸。然后烦周,把原來(lái)數(shù)組中的元素copy到新數(shù)組中來(lái),再把新元素拼接到它們后面怎顾。
? ? ? ? 而Vector長(zhǎng)度也是10读慎,超過(guò)之后new的新數(shù)組是100%延長(zhǎng)。
? ? ? ? 兩者相比槐雾,ArrayList好一些夭委,因?yàn)樗瓤梢匝娱L(zhǎng)又可以節(jié)省空間。Vector就比較浪費(fèi)空間啦蚜退。
? ? ? ? 總的來(lái)說(shuō)Vector現(xiàn)在都不用了闰靴,像這張圖中都沒(méi)有Vector:
? ? ? ? 最常用的就是加粗的這四塊。
????07-集合框架(Vector中的枚舉)
? ? ? ? 接下來(lái)講一下Vector的特點(diǎn)钻注。(不能理解既然它都不用了還要講它的特點(diǎn)是為什么。配猫。幅恋。)
? ? ? ? Collection通用的方法:
? ? ? ? Vector特有的方法(一般帶Element的都是它的特有方法):
? ? ? ? 添加元素:
? ? ? ? 查找元素:
? ? ? ? 插入:
? ? ? ? 刪除:
? ? ? ? 還有其他的:
? ? ? ? 我們來(lái)看一下這個(gè)方法:
? ? ? ? 這是什么東西鴨,木有見(jiàn)過(guò)呢:
? ? ? ? 點(diǎn)進(jìn)去這個(gè)接口看一下(這個(gè)接口叫枚舉):
? ? ? ? 那這個(gè)接口都有什么方法呢:
? ? ? ? 話(huà)不多說(shuō)泵肄,先玩一下~
? ? ? ? 枚舉就是Vector特有的取出方式捆交。
? ? ? ? 發(fā)現(xiàn)枚舉和迭代器很像。
? ? ? ? 其實(shí)腐巢,枚舉和迭代是一樣的。
? ? ? ? 因?yàn)槊杜e的名稱(chēng)以及方法的名稱(chēng)都過(guò)長(zhǎng),所以被迭代器取代了岔乔,枚舉郁郁而終了永品。
? ? ? ? 但是IO當(dāng)中有一個(gè)對(duì)象用到了枚舉,因?yàn)槟莻€(gè)對(duì)象也是1.0粗現(xiàn)的胃惜,那個(gè)時(shí)候沒(méi)有迭代泞莉,只有枚舉。
? ? ? ? Vector和ArrayList的區(qū)別是什么船殉?
? ? ? ? Vector支持枚舉鲫趁,ArrayList沒(méi)有枚舉。
????08-集合框架(LinkedList)
? ? ? ? 我們來(lái)看一看LinkedList里面有什么特有方法~
? ? ? ? 試一下利虫,addFirst:
? ? ? ? 再一次挨厚,addLast和getFirst堡僻、getLast:
? ? ? ? removeFirst:
? ? ? ? get...()和remove...()方法的區(qū)別:get可以獲取元素但不刪除元素,remove獲取元素疫剃,但是元素被刪除钉疫。
? ? ? ? 想把里面元素全取出來(lái)~
? ? ? ? 正著取:
? ? ? ? 倒著然派辍:
? ? ? ? removeFirst方法會(huì)拋出異常:
? ? ? ? 到了后期陌选,LinkedList方法升級(jí)了,它里面加了一個(gè)新的方法蹄溉,pollFirst/Last:
? ? ? ? 如果列表為空它不再拋出異常咨油,而是返回null,這是1.6版本出現(xiàn)的柒爵,以后推薦用這個(gè)方法喔役电。
? ? ? ? 獲取但不移除元素的新方法:
? ? ? ? 插入元素的新方法:
? ? ? ? 它們替代了之前舊的方法。
????09-集合框架(LinkedList練習(xí))
? ? ? ? 練習(xí):使用LinkedList模擬一個(gè)堆椕拚停或者隊(duì)列數(shù)據(jù)結(jié)構(gòu)法瑟。
? ? ? ? 描述隊(duì)列:??
? ? ? ? 封裝好之后,我們就可以直接使用啦:
? ? ? ? 注意哦唁奢,像這樣的封裝很常見(jiàn)霎挟。
? ? ? ? 為什么要封裝呢?我們直接用LinkedList不就可以完成了嗎麻掸?
? ? ? ? 但是LinkedList只有自身的含義酥夭,叫做鏈表,我們想把它做成跟我們項(xiàng)目相關(guān)的一些容器脊奋,那么我們需要起一些特定的名稱(chēng)來(lái)用更方便一些熬北,這個(gè)時(shí)候我們就會(huì)將原有的集合封裝進(jìn)我們的描述當(dāng)中,并且對(duì)外提供一個(gè)自己更容易識(shí)別的方法名稱(chēng)诚隙。
? ? ? ? 好啦讶隐,存完之后該取啦:
????10-集合框架(ArrayList練習(xí))
? ? ? ? 練習(xí):去除ArrayList中的重復(fù)元素。
? ? ? ? 思路:創(chuàng)建一個(gè)新容器久又,將舊容器的東西一個(gè)個(gè)放進(jìn)去巫延,放的時(shí)候判斷它是否已存在在新容器~
? ? ? ? 代碼:?
? ? ? ? 接下來(lái)刪除重復(fù)的:
????11-集合框架(ArrayList練習(xí)2)
? ? ? ? 練習(xí):將自定義對(duì)象作為元素存儲(chǔ)到ArrayList集合總,并去除重復(fù)元素籽孙。
? ? ? ? ? ? ? ? ? ?比如:存人對(duì)象烈评。將同姓名同年齡,視為同一個(gè)人犯建,為重復(fù)元素讲冠。
? ? ? ? 思路:
? ? ? ? Person類(lèi):
? ? ? ? 主函數(shù)中:
? ? ? ? 可是為什么這樣寫(xiě)會(huì)出錯(cuò)呢?
? ? ? ? 因?yàn)樵谕萜骼锩娲鍼erson的時(shí)候适瓦,add的其實(shí)是Object竿开,al.add(Object obj)谱仪,因?yàn)橹挥兴芙邮杖我鈱?duì)象。把Person傳進(jìn)去否彩,其實(shí)相當(dāng)于Object obj=new Person("lisi01",30);疯攒,這時(shí)Person就被提升為Object了。而后面的it.next()往回返的時(shí)候列荔,返回的是Object敬尺,Object中并沒(méi)有g(shù)etName方法,多態(tài)編譯失敗贴浙。
? ? ? ? 應(yīng)該改成這樣:
? ? ? ? 兩句合一句:
? ? ? ? 下面一句話(huà)也改一下:
? ? ? ? 運(yùn)行:
? ? ? ? 搞定砂吞。
? ? ? ? 接下來(lái)去重。
? ? ? ? 將之前寫(xiě)好的singleElement方法直接拿過(guò)來(lái)用:
? ? ? ? 我們可以看到崎溃,contains方法中其實(shí)調(diào)用了equals方法:
? ? ? ? 而默認(rèn)的equals方法顯然不適用于判斷我們新建立的對(duì)象蜻直,所以我們要在Person類(lèi)中重寫(xiě)equals方法:
? ? ? ? 調(diào)用singleElement方法:
? ? ? ? 刪除成功:
? ? ? ?List集合判斷元素是否相同,依據(jù)的是元素的equals方法袁串。 (其他的集合肯定不一樣)
? ? ? ? 雖然主函數(shù)中沒(méi)有直接調(diào)用equals方法概而,但是因?yàn)閏ontains方法調(diào)用了equals方法,而singleElement方法又調(diào)用了contains方法囱修。
? ? ? ? 這個(gè)問(wèn)題搞明白之后赎瑰,我們還會(huì)明白一系列其他問(wèn)題。
? ? ? ? 先將重寫(xiě)的equals方法注釋掉破镰,我們現(xiàn)在刪除一下其中一個(gè)元素:
? ? ? ? 但運(yùn)行結(jié)果是false而且刪除失敗了:
? ? ? ? 為什么呢乡范?
? ? ? ? 因?yàn)橐獎(jiǎng)h除這個(gè)元素,就得現(xiàn)在容器中尋找這個(gè)元素啤咽。remove底層也調(diào)用了equals。而默認(rèn)的equals方法是對(duì)比對(duì)象是否是同一個(gè)渠脉,new的Person是新的對(duì)象宇整,地址值不相同,所以肯定會(huì)刪除失敗芋膘。
? ? ? ? 現(xiàn)在將重寫(xiě)后的equals方法去掉注釋?zhuān)?/b>再試一下:
? ? ? ? 成功啦鳞青。
????12-集合框架(HashSet)
? ? ? ? 講完了List,那么ArrayList和LinkedList該用哪一個(gè)呢为朋?
? ? ? ? 如果元素中涉及了頻繁的增刪操作臂拓,用LinkedList。
? ? ? ? 如果增刪操作不頻繁习寸,可以選擇用LinkList胶惰,也可以選擇用ArrayList。
? ? ? ? 如果涉及了增刪霞溪,同時(shí)又涉及了查詢(xún)孵滞,建議使用ArrayList中捆。因?yàn)槠鋵?shí)頻繁的增刪操作并不多見(jiàn),一般的情況下都是查詢(xún)比較多坊饶。所以ArrayList作為一個(gè)最常見(jiàn)泄伪、最大頻率使用的容器存在,當(dāng)實(shí)在不知道該用誰(shuí)匿级,就用ArrayList蟋滴。
? ? ? ? List派系講完啦,接下來(lái)講Set派系痘绎。
? ? ? ? |——Set:元素是無(wú)序(存入和取出的順序不一定一致)津函,元素不可以重復(fù)。(想重復(fù)找List简逮,不重復(fù)找Set)
????????????????|——HashSet:底層數(shù)據(jù)結(jié)構(gòu)是哈希表球散。
? ? ? ? ? ? ? ? |——TreeSet:
? ? ? ? 看一下Set接口的方法,發(fā)現(xiàn)Set集合的功能和Colletion是一致的散庶。Colletion的方法我們之前都講過(guò)啦蕉堰,所以就不重復(fù)講啦。
? ? ? ? 每個(gè)對(duì)象都有哈希值悲龟,那什么是哈希表呢?
? ? ? ? 示例:
? ? ? ? ?發(fā)現(xiàn)它們都有哈希值:
? ? ? ? 接下來(lái)講講什么是哈希表:
? ? ? ? 很簡(jiǎn)單屋讶,存放哈希值的表就叫哈希表。哈希表的順序和元素的存放順序無(wú)關(guān)须教,和哈希值的大小有關(guān)皿渗。而取元素的時(shí)候也是按哈希值來(lái)取。
? ? ? ? 那會(huì)不會(huì)有哈希值相同的情況呢轻腺?
? ? ? ? 若哈希值相同乐疆,會(huì)判斷哈希值所指的對(duì)象是否相同,若不同贬养,會(huì)在這個(gè)哈希值上再向下順延一個(gè)挤土,表中有兩個(gè)這個(gè)哈希值(不知道我理解的對(duì)不對(duì),如果相同误算,那該怎么找對(duì)應(yīng)的對(duì)象呢):
? ? ? ? 驗(yàn)證無(wú)序:
? ? ? ? 驗(yàn)證唯一性:
????13-集合框架(HashSet存儲(chǔ)自定義對(duì)象)
? ? ? ? 還和11中的例子一樣仰美,存儲(chǔ)Person到HashSet中。? ? ?
? ? ? ? 將那個(gè)例子中的代碼都復(fù)制了過(guò)來(lái)儿礼,主函數(shù)中這樣寫(xiě):? ?
? ? ? ? 我們?cè)僭囋嚧嫒胫貜?fù)的Person對(duì)象咖杂,發(fā)現(xiàn)成功了:
? ? ? ? 為什么即使重寫(xiě)了equals方法,還是會(huì)出現(xiàn)重復(fù)呢蚊夫?
? ? ? ? 因?yàn)楝F(xiàn)在往里面存的四個(gè)對(duì)象都是獨(dú)立的诉字,都有獨(dú)立的哈希值,都存入了哈希表。
? ? ? ? 而我們現(xiàn)在要做的奏窑,就是覆蓋Person的哈希值方法导披,建立Person對(duì)象自己的哈希值。
? ? ? ? 怎么建立哈希值呢埃唯?
? ? ? ? 你的判斷條件是什么撩匕,我就依據(jù)你的條件來(lái)建立哈希值。比如這里是按照姓名和年齡來(lái)判斷對(duì)象是否重復(fù)的墨叛,那我們就按照姓名和年齡來(lái)建立哈希值止毕。
? ? ? ? 代碼:
? ? ? ? 注意,只有當(dāng)哈希值相同時(shí)漠趁,才會(huì)調(diào)用equals方法對(duì)比內(nèi)容是否相同扁凛。
? ? ? ??|——Set:元素是無(wú)序(存入和取出的順序不一定一致),元素不可以重復(fù)闯传。(想重復(fù)找List谨朝,不重復(fù)找Set)
????????????????|——HashSet:底層數(shù)據(jù)結(jié)構(gòu)是哈希表。
? ? ? ? ? ? ? ? ? ? ? ? HashSet是如何保證元素唯一性的呢甥绿?
? ? ? ? ? ? ? ? ? ? ? ? 是通過(guò)元素的兩個(gè)方法字币,hashCode和equals來(lái)完成。
? ? ? ? ? ? ? ? ? ? ? ? 如果元素的HashCode值相同共缕,才會(huì)判斷equals是否為true洗出。
? ? ? ? ? ? ? ? ? ? ? ? 如果元素的hashcode值不同,不會(huì)調(diào)用equals图谷。
? ? ? ? ? ? ? ? |——TreeSet:
? ? ????所以注意翩活,在開(kāi)發(fā)中,只要描述的對(duì)象要往哈希集合中存時(shí)便贵,一般都會(huì)復(fù)寫(xiě)hashCode和equals菠镇。? ??
? ? ? ? 還有注意,為了保證哈希值的唯一性承璃,一般會(huì)給這里乘個(gè)數(shù)字(兩個(gè)對(duì)象萬(wàn)一兩部分加起來(lái)正好是同一個(gè)值就重復(fù)了):
????14-集合框架(HashSet判斷和刪除的依據(jù))
? ? ? ? 注意辟犀,HashSet對(duì)于判斷元素是否存在,以及刪除等操作绸硕,依賴(lài)的方法是元素的hashCode和equals方法,而且先依賴(lài)hashCode魂毁,再依賴(lài)equals玻佩。
? ? ? ? ArrayList判斷元素是否存在,以及刪除等操作席楚,只依賴(lài)equals咬崔。
? ? ? ? 這個(gè)原因全都在數(shù)據(jù)結(jié)構(gòu)上,數(shù)據(jù)結(jié)構(gòu)不同,它依賴(lài)的方法也不一樣垮斯。? ??