(1)長度可變
(2)只能存儲(chǔ)引用類型
(3)不使用泛型時(shí)椭微,存儲(chǔ)對(duì)象可以不是同種數(shù)組類型
Collection接口
1.添加为朋,刪除
2.判斷
3.集合大小
4.獲取集合元素
(collection中沒有獲取角標(biāo)的方法竹祷,所以無法獲取指定元素)
(1)增強(qiáng)for循環(huán)? for(Object o:collection)
(2)Iterator iterator() 迭代器
迭代器一開始的位置是第一個(gè)元素的前面
常用方法:
next()? 下一個(gè)元素? ? hasNext() 是否還有元素? remove()刪除元素? ? ? ?
注意next()方法必須放在remove()方法之前寝并,不然由于不斷remove(),調(diào)用next()方法不確定是哪一個(gè)元素remove依賴next,如果remove之前沒有調(diào)用next是不合法的寂曹。
常見問題
? ? ? ? 在迭代的過程中哎迄,想要?jiǎng)h除當(dāng)前元素的時(shí)候不可以調(diào)用集合的remove()方法,只能調(diào)用迭代器的remove()方法
原因:這個(gè)過程就像是抓娃娃的過程隆圆,集合相當(dāng)與娃娃機(jī)的擁有者芬失,迭代器相當(dāng)娃娃機(jī)的使用者,當(dāng)使用者使用娃娃機(jī)的時(shí)候就臨時(shí)獲得了娃娃機(jī)的絕對(duì)控制權(quán)匾灶,絕不可能允許擁有者棱烂,從娃娃機(jī)里拿出元素,而只能通過使用者拿出元素從而減少娃娃機(jī)內(nèi)中娃娃的數(shù)量阶女。
例題:獲取集合中數(shù)字颊糜,并求其和
5.集合和數(shù)組之間的轉(zhuǎn)換
數(shù)組----》集合? ? Arrays.asList(數(shù)組)
注:1數(shù)組轉(zhuǎn)換集合的時(shí)候數(shù)組里面只能是引用數(shù)據(jù)類型,如果基本數(shù)據(jù)類型轉(zhuǎn)換的集合就是一個(gè)對(duì)象整體秃踩,會(huì)把數(shù)組當(dāng)成一個(gè)整體來看待衬鱼。
? ? 2. 當(dāng)數(shù)組轉(zhuǎn)換成集合的時(shí)候,不能做一些增刪的操作憔杨,因?yàn)檗D(zhuǎn)換成的集合其本質(zhì)還是一個(gè)數(shù)組鸟赫。(其實(shí)返回的不是一個(gè)ArrayList而是一個(gè)視圖)
集合---》數(shù)組? ? ? 集合對(duì)象.toArray()
不建議使用Collection作為父類引用,因?yàn)橛行┓椒ú痪邆?/p>
List接口:
有序可重復(fù)的,有序指的是存入順序
ArrayList:底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組抛蚤,查詢元素快台谢,增刪改慢 ,線程不同步
LinkedList: 底層數(shù)據(jù)結(jié)構(gòu)是鏈表岁经,增刪改塊朋沮,查詢慢,線程不同步
Vector:特別慢不推薦使用? ? 線程同步
具有Collection所有方法
特有方法(注意set方法缀壤,返回值是被替換的值)
特有的迭代器? ListIterator
特有方法 (可以實(shí)現(xiàn)倒敘遍歷)
LinkedList特有方法
棧:push pop ?后進(jìn)先出 ? 隊(duì)列 ?:先進(jìn)先出
Collections:
一個(gè)工具類樊拓,提供了一些操作List集合的功能,都是靜態(tài)方法
? ? ? sort的方法實(shí)現(xiàn)的時(shí)候塘慕,集合的里的類中一定要有自己的比較方法筋夏,也就是說類實(shí)現(xiàn)comparable接口重寫比較方法,因?yàn)閟ort方法在定義時(shí)使用泛型图呢,規(guī)定傳入list的集合中的類必須實(shí)現(xiàn)了Comparable接口叁丧。
Set接口:
因?yàn)闊o序所以沒有g(shù)et和set方法,因此不能室友普通for循環(huán)
無序岳瞭,不可重復(fù),添加類對(duì)象時(shí)蚊锹,類內(nèi)部重寫了equals才能更準(zhǔn)確實(shí)現(xiàn)不可重復(fù)
面試題
去除List集合中的重復(fù)數(shù)據(jù)? ? List--》Set(set轉(zhuǎn)換為List也可以這么轉(zhuǎn)換)
1.HashSet:底層數(shù)據(jù)結(jié)構(gòu)是哈希表瞳筏,保證元素唯一性,線程不同步
2.TreeSet:進(jìn)行指定順序排列 牡昆,線程不同步
Hashset存儲(chǔ)原理
當(dāng)向set集合中存儲(chǔ)數(shù)據(jù)的時(shí)候姚炕,首先會(huì)比較兩個(gè)對(duì)象hashcode(重寫方法,假設(shè)同對(duì)象hashCode就相同)丢烘,如果hashcode值不一樣的話柱宦,就認(rèn)為兩個(gè)對(duì)象不相同可以存儲(chǔ),如果兩個(gè)對(duì)象hashcode值相同的話則去調(diào)用equals方法分別比較兩個(gè)對(duì)象中每個(gè)屬性是否相同播瞳,如果不同則可以存儲(chǔ)掸刊,如果相同則不可以存儲(chǔ)
Hashcode:返回對(duì)象的hash值,hash值是通過某種計(jì)算規(guī)則獲取到的一個(gè)int類型的數(shù)值
HashSet和ArrayList集合都有判斷元素是否相同的方法赢乓,
boolean contains(Object o)
HashSet使用hashCode和equals方法忧侧,ArrayList使用了equals方法
LinkedHashSet
帶有鏈表的式的集合該集合為了完善set集合無序的特點(diǎn)
TreeSet(防重復(fù)與HashSet相同)
默認(rèn)采用了了排序
1.自然排序(sort()方法,其中集合所存類必須實(shí)現(xiàn)comparable接口牌芋,重寫compareTo()方法)
? 對(duì)于compareTo方法來說返回1代表換位蚓炬,0代表對(duì)象相等,-1不換位躺屁,(true相當(dāng)1肯夏,false相當(dāng)-1)
自然排序只能實(shí)現(xiàn)一次(也就是不能排序了一種信息后,想要用另一種信息進(jìn)行排序是不可能的,但是如果按照一種排序驯击,如果這種排序相等再進(jìn)行另一種排序是可能)烁兰,也就是不能對(duì)第二種信息進(jìn)行排序(),由此引出定制排序(比較器)可以在創(chuàng)建TreeSet時(shí)余耽,在其構(gòu)造器能創(chuàng)建比較的匿名內(nèi)部類
2.定制排序:建議使用匿名內(nèi)部類缚柏,因?yàn)槎ㄖ婆判蚩赡苤粦?yīng)用一次,在構(gòu)造方法添加Comparator實(shí)現(xiàn)類碟贾。
調(diào)用單一參數(shù)的sort(List l)方法代表由list元素(元素指集合內(nèi)的類)上的compare方法決定順序币喧,
調(diào)用sort(List o,Comparator c)方法代表不會(huì)調(diào)用compareTo()方法袱耽,(建立內(nèi)部類實(shí)現(xiàn)Comparator接口杀餐,重寫compare()方法)
構(gòu)造方法TreeSet(ComparatorE> comparator) ,因?yàn)閰?shù)是一個(gè)接口朱巨,所以比較創(chuàng)建一個(gè)接口類子類的對(duì)象
Map
? (同樣重寫了equals和hashcode)
存鍵值對(duì)
Map元素實(shí)際是兩個(gè)對(duì)象: 關(guān)鍵字key和值value 史翘,key不能重復(fù),value可以重復(fù)冀续,如果存儲(chǔ)相同的key后面存入的值會(huì)把之前的key所對(duì)應(yīng)的值替換掉
注:可存null值
1.添加刪除
2.判斷
3.獲取
HashSet? ? ? ? LinkedHashMap? 與LinkedHashSet目的相同
存儲(chǔ)原理:HashMap的key的值的存儲(chǔ)原理與HashSet的存儲(chǔ)原理一樣
Hashtable(線程安全)琼讽,不可以存null的key常被HashMap代替
Properties(了解):類似map(是map的一個(gè)子類)但是鍵值都是String型,該集合通常用于對(duì)鍵值對(duì)形式的配置文件進(jìn)行操作.
配置文件:將軟件中可變的部分?jǐn)?shù)據(jù)可以定義到一個(gè)文件中洪唐,方便以后更改钻蹬,該文件稱之為配置文件。
在以后開發(fā)的過程當(dāng)中經(jīng)常會(huì)使用到properties配置文件凭需,該配置文件里面會(huì)保存一些數(shù)據(jù)问欠,該配置文件所對(duì)應(yīng)的類就是Properties
TreeMap:底層key與TreeSet相同,也就是說要實(shí)現(xiàn)接口重寫方法粒蜈,所以當(dāng)你使用TreeMap的時(shí)候顺献,里面所存類必須實(shí)現(xiàn)接口重寫方法,不然會(huì)報(bào)錯(cuò)枯怖。
TreeMap默認(rèn)是按照key進(jìn)行排序的注整,如果想要針對(duì)value進(jìn)行遍歷需要把他轉(zhuǎn)換為list集合,但是其實(shí)將key與value交換位置會(huì)更好
紅黑樹(二叉樹)
TreeSet和TreeMap可以實(shí)現(xiàn)排序度硝,但是底層數(shù)據(jù)結(jié)構(gòu)又是怎么存的呢设捐?
存儲(chǔ)原理:第一個(gè)數(shù)存進(jìn)來,放在最頂端塘淑,當(dāng)?shù)诙?shù)12來的時(shí)候萝招,因?yàn)楸?3小,就放在了23樹分叉的左側(cè)存捺,假如第三個(gè)數(shù)是13槐沼,那么它先和23比較曙蒸,小與側(cè)左側(cè)分支
獲取所有項(xiàng)
由于Map沒有迭代器,而增強(qiáng)for循環(huán)其實(shí)就是迭代器的一個(gè)簡化版本岗钩,所以也不能使用增強(qiáng)for循環(huán)纽窟,因此只能通過將他map轉(zhuǎn)換為set來實(shí)現(xiàn)
1.keySet
keySet原理是先將Key轉(zhuǎn)換為Set幾個(gè),然后通過mao.get(Key)得到value的值兼吓,從而實(shí)現(xiàn)遍歷
2.entrySet
此時(shí)返回的Set中的Entry存的是一組組映射關(guān)系臂港,這時(shí)通過getKey()和getValue()方法拆解映射關(guān)系
Entry是Set接口里的內(nèi)部接口,這個(gè)接口中有g(shù)etKey()和getValue()方法
3.values
直接遍歷map集合中的value值
List集合與一般數(shù)組區(qū)別
1.一般數(shù)組在創(chuàng)建就必須知道大小视搏,ArrayList會(huì)在調(diào)用方法時(shí)變大小
2.存放對(duì)象給一般數(shù)組必須指定位置审孽,ArrayList可以指定位置,也可以不指定
3.ArrayList使用泛型浑娜,已確保添加進(jìn)去的都是同已類型佑力,而數(shù)組在定義的時(shí)候直接就確定存儲(chǔ)的類型
? ? ? ? 數(shù)組就像身上編了號(hào)站成一排的人,要找第10個(gè)人很容易筋遭,根據(jù)人身上的編號(hào)很快就能找到打颤。但插入、刪除慢漓滔,要往某個(gè)位置插入或刪除一個(gè)人時(shí)编饺,后面的人身上的編號(hào)都要變。當(dāng)然响驴,加入或刪除的人始終末尾的也快透且。
鏈表就像手牽著手站成一圈的人,要找第10個(gè)人不容易踏施,必須從第一個(gè)人一個(gè)個(gè)數(shù)過去。但插入罕邀、刪除快畅形。插入時(shí)只要解開兩個(gè)人的手,并重新牽上新加進(jìn)來的人的手就可以诉探。刪除一樣的道理日熬。
Java中,ArrayList肾胯、LinkedList就是分別用數(shù)組和鏈表做內(nèi)部實(shí)現(xiàn)的竖席。
集合的選擇
Array? 查詢快,增減慢
Link? 增減快敬肚,查詢慢毕荐,因此鏈表不推薦使用get()方法,所以迭代最好不用for循環(huán)
hash? ? ? 唯一性艳馒,類中重寫hashCode憎亚,equals方法
tree? ? 排序员寇,調(diào)用類實(shí)現(xiàn)接口重寫方法
map和set都不能出入重復(fù)元素,set用add存入重復(fù)元素第美,會(huì)返回false蝶锋,而map存入重復(fù)元素,value會(huì)覆蓋原來value值
存儲(chǔ)是一個(gè)元素用collection
存儲(chǔ)一對(duì)元素什往,元素間有映射關(guān)系扳缕,用Map
保證唯一性用Set(注重獨(dú)一無二的性質(zhì))
不保證用List(快,因?yàn)镾et要不斷比較)(是對(duì)付順序的好幫手别威,知道索引位置)
泛型
更好的類型安全性躯舔,大多數(shù)應(yīng)用于泛型,確保集合放入同類對(duì)象兔港,它可以防止把Dog加到一群Cat三種庸毫,如果< Object> 表示只能放入Object對(duì)象,不能放入其它的對(duì)象衫樊,它的子類也不可以飒赃,因?yàn)椴荒芘袛喑鍪撬哪膫€(gè)子類,但是可以放入它的父類科侈。類似于只取到了Object的遙控器
沒有泛型的時(shí)候载佳,集合默認(rèn)傳入的是Object類型,應(yīng)用泛型臀栈,讓問題在編譯器就能被抓到蔫慧,而不會(huì)等到運(yùn)行的時(shí)候才冒出來,如果沒有泛型权薯,編譯器會(huì)很愉快地接收你把綿羊?qū)ο笏偷嚼匣⒓现?/p>
沒泛型傳入一個(gè)fish類型姑躲,出來的是一個(gè)Object類型,有泛型傳入什么類型出來什么類型
常用泛型的地方:
1.創(chuàng)建被泛型化類的實(shí)例盟蚣,聲明與指定泛型類型的變量
List <Song>songList=new ArrayList<Song>()
2.聲明取用泛型類型的方法
void foo(List<Song> list)? 這時(shí)候方法接收的實(shí)參集合必須是Song類型
以下為了解(在定義類接口黍析,方法的時(shí)候使用泛型,此時(shí)相當(dāng)是形參屎开,當(dāng)創(chuàng)建對(duì)象時(shí)明確泛型相當(dāng)實(shí)參)
泛型類
class 類名<Q> ? 創(chuàng)建對(duì)象時(shí)要指定具體類型
泛型接口
interface 接口名<Q>
當(dāng)父類和子類加上泛型后阐枣,兩個(gè)類就不是繼承關(guān)系了
泛型方法
public T getData(T data) {
returndata;
不確定傳入的是什么類型,就要把傳入的值返回 ?奄抽,靜態(tài)方法不可行蔼两,因?yàn)榉盒偷拇_定與對(duì)象有關(guān)
? ? ? 當(dāng)數(shù)組的時(shí)候,animals型數(shù)組可以傳入所有它的子類對(duì)象逞度,那么集合也可以實(shí)現(xiàn)這個(gè)功能么额划?而上述說的泛型比如
ArrayList<Animals>? 只能傳入animals型,傳入它的子類是絕對(duì)不可能的档泽,那么到底要如何實(shí)現(xiàn)呢锁孟?彬祖,但是為什么數(shù)組可以傳呢?這是因?yàn)閿?shù)組是運(yùn)行期檢查品抽,而集合是編譯期檢查
為了解決這個(gè)問題出現(xiàn)了通配符
通配符? 储笑?? 可以作為任何類型
泛型限定
上限:? ? extends E:往集合填充元素的時(shí)候圆恤,往集合添加元素是E或者其子類
只有類在聲明泛型時(shí)是? 突倍? extends E? ? 才可以ArrayList <Dog>al=new ArrayList<Animals>();
否則泛型必須統(tǒng)一,子類也不可以
下線 :? 盆昙? supper E? 從集合獲取元素羽历,獲取的是元素E和其父類