Java 之路 (十一) -- 持有對象(Collection、List掩缓、Set雪情、Queue、Map你辣、Iterator巡通、foreach)

本章將簡單介紹一下常用的集合類的特點,同時并不會深入源碼分析原理舍哄,本文目的僅僅在于對 Java 集合類有一個整體認識

關于 API宴凉,本文不涉及過多,建議直接查看 Java 官方文檔

https://docs.oracle.com/javase/9/docs/api/overview-summary.html


1. 容器概述

1.1 引入原因

Java 中表悬,數組用來保存一組對象弥锄,但是數組具有固定的尺寸。于是為了解決數組長度固定蟆沫,無法應對對象數量未知的情況籽暇,引入容器/集合類。

容器用途就是保存對象饭庞。

1.2 容器層級

容器有兩大山脈:Collection 和 Map戒悠,其層次關系大致如下。

先來個基礎的:

img

https://www.cnblogs.com/LipeiNet/p/5888513.html

再來個復雜一點的:

img

圖摘自 http://www.cnblogs.com/leeplogs/p/5891861.html

其中:

  • Collection 接口是集合類的根接口舟山,本身沒有實現類绸狐。
  • Map 是容器的另一個根接口卤恳,與 Collection 相互獨立
  • Iterator 是所有容器都實現的接口,用于遍歷容器中元素寒矿。
  • 另外 Collections 和 Arrays 是 Object 的直接子類纬黎,其中包含了一系列關于 容器 和 數組 的靜態(tài)方法

1.3 類型安全

通過 泛型 指定參數類型,即指定這個容器實例可以保存的類型劫窒。通過使用泛型,可以在編譯期防止將錯誤類型的對象放置到容器中拆座。

保證 類型安全 僅僅是 Java 泛型的其中一個作用主巍。后續(xù)我們會學習更多關于 泛型的知識(劇透一下,很復雜)

舉個例子:

List<String> list = new ArrayList<String>();

//先不用管 List 和 ArrayList 是啥挪凑,就先當作是一個集合就好
//通過指定泛型為 String孕索,那么這個集合就是用來存放 String 類型的,放入其他類型的東西都會出錯躏碳。

2. Collection

Collection 是一個接口搞旭,它下面的 List,Set菇绵,Queue 同樣也都是接口肄渗。

一個獨立元素的序列,這些元素都服從一條或多條規(guī)則咬最。其中 List 必須按照插入的順序保存元素翎嫡;Set 不能有重復元素;Queue 按照排隊規(guī)則來確定對象的產生順序(通常與插入順序相同)

2.1 List

List 是一個接口永乌,它承諾可以將元素維護在特定的序列中惑申。List 接口在 Collection 的基礎上添加大量的方法,使得可以在 List 中間插入和移除元素翅雏。

  • 有序
  • 元素可重復

下面主要介紹 兩種 List :ArrayList 和 LinkedList圈驼。

2.1.1 ArrayList

優(yōu)點在于隨機訪問元素快,但是在中間插入和移除比較慢

原因是 ArrayList 底層是用數組實現的望几,這也是為什么讀取時和數組效率相同绩脆,時間復雜度都是1.

2.1.2 LinkedList

優(yōu)點是善于在中間插入和移除元素,提供了優(yōu)化的順序訪問橄妆,相反缺點是隨機訪問較慢

原因是底層是使用鏈式存儲

同時衙伶,LinkedList 可以實現比 ArrayList 更多的功能特性:LinkedList 支持棧、隊列和雙端隊列害碾。

2.1.3 Stack

Stack(棧)通常指 “后進先出”(LIFO)的容器矢劲,最后一個壓入棧的元素,第一個彈出棧慌随。

可以想象為彈簧芬沉,最先放上彈簧的被放在最下面躺同,后放上去的在上面,每次彈出來一個時丸逸,上面的(后放的)先被彈出蹋艺。

Stack 是通過 LinkedList 實現的

Stack 繼承自 Vector黄刚,而 Vector 已被棄用瓜晤。

2.2 Set

Set 也是一個集合帅韧,但是它不保存重復的元素。

Set 具有和 Collection 完全一樣的接口,因此沒有任何額外的功能医舆,實際上 Set 就是 Collection分预,只不過行為不同叮称。

繼承與多態(tài)思想的應用:表現不同的行為

下面簡單介紹兩個實現類:HashSet 和 TreeSet

2.2.1 HashSet

  • 查詢速度塊酣藻。HashSet 使用了散列,散列的價值在于速度 -- 散列使得查詢更加快速

  • 存儲無序

    HashSet 底層使用散列函數

2.2.2 TreeSet

  • 存儲有序

    TreeSet 將元素存儲在紅黑樹中程储,因此存儲結果有序蹭沛。

2.2.3 LinkedHashSet

  • 存儲有序

    通過鏈表保存添加的順序

2.3 Queue

Queue (隊列)是典型的 先進先出 的容器,即從一端放入事物章鲤,從另一端取出摊灭,且元素放入容器的順序和取出的順序是相同的。

可以想象一個傳送帶败徊,先放上傳送帶的物品會首先到達斟或。

同時 Queue 中允許重復元素。

LinkedList 實現了 Queue 接口集嵌,因此 LinkedList 可以用作 Queue 的一種實現(將LinkedList 可以向上轉型為 Queue)萝挤。

相關方法介紹:

方法 作用 說明
add、offer 將元素插入隊尾 隊列容量已滿時<br />add 會拋出異常<br />offer會返回 false
element根欧、peek 返回對頭元素(不刪除) 隊列為空時<br />emelent 會拋出異常<br />peek會返回 null
remove怜珍、poll 返回對頭元素,并將該元素從隊列移除 隊列為空時<br />remove 會拋出異常<br />poll 會返回 null

2.3.1 PriorityQueue

  • 先入先出描述的是下一個元素應該是等待時間最長的元素

  • PriorityQueue(優(yōu)先級隊列)描述的是下一個元素應該是優(yōu)先級最高的元素凤粗。

當我們在 PriorityQueue 上調用 offer() 插入元素的時候酥泛,這個元素會在隊列中自動被排序,默認情況是自然排序嫌拣。當然我們可以通過自定義 Comparator 來修改這個順序柔袁。

PriorityQueue 保證我們調用 peek、poll 等方法時异逐,返回的是隊列中優(yōu)先級最高的元素捶索。


3. Map

Map 就是一組成對的 “鍵值對” 對象,允許使用鍵來查找值灰瞻。Map 可以將對象映射到其他對象上腥例,在實際開發(fā)中使用非常廣辅甥。

主要方法介紹:

方法 用途
put 添加鍵值對元素
get 返回與鍵對應的值
containsKey 查詢是否包含某個鍵
containsValue 查詢是否包含某個值
keySet 返回鍵的 set
entrySet 返回鍵值對的 set
values 返回值的 collection

3.1 HashMap

  • 查詢速度很快

  • 存儲無序

    原因在于,底層使用了 散列函數

  • 鍵可以是 null燎竖,鍵值不可重復(重復會覆蓋舊的)

3.2 TreeMap

  • 按照比較結果的升序保存鍵

    紅黑樹存儲

3.3 LinkedHashMap

  • 按照插入順序保存鍵

  • 保留了 HashMap 的查詢速度

    底層使用了散列函數 璃弄,同時用一個鏈表保存插入順序。


4. 迭代器

4.1 概念

Java 中的迭代器(Iterator):

  • 是一個輕量級對象:創(chuàng)建代價小
  • 工作是遍歷并選擇序列中的對象构回,不關注容器中元素的數量
  • 只能單向移動

4.2 用處:

  • 使用方法 iterator() 要求容器返回一個 Iterator夏块,此時 Iterator 將準備好返回第一個元素
  • 使用 next() 獲得序列下一個元素
  • 使用 hasNext() 檢查序列中是否還有元素
  • 使用 remove() 將迭代器最近返回的元素刪除

4.3 ListIterator

ListIterator 是 Iterator 的子類型,只能用于各種 List 類的訪問纤掸。

ListIterator 可以雙向移動拨扶,它可以產生相對于迭代器在列表中指向的當前位置的前一個(previous()方法)和后一個元素的索引(next() 方法)。

4.4 Iterator 與 foreach

foreach 除了可以作用于數組茁肠,還可以應用于所有的 Collection 對象。這是因為 Collection 繼承了 Iterable 的接口缩举。該接口包含一個能夠產生 iterator 的 iterator() 對象垦梆,并且 Iterable 接口被 foreach 用來在序列中移動。

public class IterableClass implements Iterable<String> {
    protected String[] words=("Hello Java").split(" ");
    
    public Iterator<String> iterator(){
        return new Iterator<String>(){
            private int index=0;
            public boolean hasNext() {
                return index<words.length;
            }
            public String next() {
                return words[index++];
            }
            public void remove() {
            }
        };
    }
    public static void main(String[] args){
        for(String s : new iterableClass())
            System.out.println(s + "");
    }
}

//輸出:
//Hello Java

5. Collections 和 Arrays

Collections 和 Arrays 都是 Object 的直接子類仅孩,里面封裝了一系列關于集合和數組的靜態(tài)方法托猩。

部分方法如下:

  • Collections.addAll():用于將一些列元素加入到 Collection

    public static <T> boolean addAll(Collection<? super T> c, T... elements)

  • Arrays.asList():將數組(可變參數列表)寫入到一個列表,并將該列表返回

    public static <T> List<T> asList(T... a)

    底層表示為數組辽慕,因此不能修改尺寸京腥。如果調用add() 或 delete(),有可能改變數組尺寸溅蛉,因此會報錯公浪。

  • Arrays.toString():產生數組的可打印表示。


總結

Java 提供大量持有對象的方式:

  1. 數組是將數字和對象聯系起來船侧,它保存明確的對象欠气,查詢對象時候不需要對查詢結果進行轉換,它可以是多維的镜撩,可以保存基本類型的數據预柒,但是數組一旦生成,其容量不能改變袁梗。所以數組是不可以直接刪除和添加元素宜鸯。
  2. Collection 保存單一的元素,而 Map 保存相關聯的值鍵對遮怜,有了 Java 泛型淋袖,可以指定容器存放對象類型,不會將錯誤類型的對象放在容器中锯梁,取元素時候也不需要轉型适贸。而且 Collection 和 Map 都可以自動調整其尺寸灸芳。容器不可以持有基本類型。
  3. 像數組一樣拜姿,List 也建立數字索引和對象的關聯烙样,因此,數組和 List 都是排好序的容器蕊肥,List 可以自動擴容
  4. 如果需要大量的隨機訪問就要使用 ArrayList谒获,如果要經常從中間插入和刪除就要使用 LinkedList。
  5. 各種 Queue 和 Stack 由 LinkedList 支持
  6. Map 是一種將對象(而非數字)與對象相關聯的設計壁却。HashMap 用于快速訪問批狱,TreeMap 保持鍵始終處于排序狀態(tài),所以不如 HashMap 快展东,而 LinkedHashMap 保持元素插入的順序赔硫,但是也通過散列提供了快速訪問的能力
  7. Set 不接受重復的元素,HashSet 提供最快的訪問能力盐肃,TreeSet 保持元素排序狀態(tài)爪膊,LinkedHashSet 以插入順序保存元素。
  8. 不應使用過時的 Vector砸王、HashTable

回顧一下開篇的簡圖:

不包含抽象類和遺留構件

可以發(fā)現其實只有四種容器 -- List推盛、Set、Queue谦铃、Map耘成。常用的用紅色標出,綠色標識接口驹闰,其他標識普通的類瘪菌。

使用時需要注意容器類之間方法的獨立性:有些相同,而有些相差很遠嘹朗。

上述即為本章的全部控嗜,共勉。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末骡显,一起剝皮案震驚了整個濱河市疆栏,隨后出現的幾起案子,更是在濱河造成了極大的恐慌惫谤,老刑警劉巖壁顶,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異溜歪,居然都是意外死亡若专,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門蝴猪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來调衰,“玉大人膊爪,你說我怎么就攤上這事『坷颍” “怎么了米酬?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長趋箩。 經常有香客問我赃额,道長,這世上最難降的妖魔是什么叫确? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任跳芳,我火速辦了婚禮,結果婚禮上竹勉,老公的妹妹穿的比我還像新娘飞盆。我一直安慰自己,他們只是感情好次乓,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布吓歇。 她就那樣靜靜地躺著,像睡著了一般檬输。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上匈棘,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天丧慈,我揣著相機與錄音,去河邊找鬼主卫。 笑死逃默,一個胖子當著我的面吹牛,可吹牛的內容都是我干的簇搅。 我是一名探鬼主播完域,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瘩将!你這毒婦竟也來了吟税?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤姿现,失蹤者是張志新(化名)和其女友劉穎肠仪,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體备典,經...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡异旧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了提佣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吮蛹。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡荤崇,死狀恐怖,靈堂內的尸體忽然破棺而出潮针,到底是詐尸還是另有隱情术荤,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布然低,位于F島的核電站喜每,受9級特大地震影響,放射性物質發(fā)生泄漏雳攘。R本人自食惡果不足惜带兜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吨灭。 院中可真熱鬧刚照,春花似錦、人聲如沸喧兄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吠冤。三九已至浑彰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拯辙,已是汗流浹背郭变。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留涯保,地道東北人诉濒。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像夕春,于是被迫代替她去往敵國和親未荒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內容