Java集合的使用:List与Map
由David發(fā)表在天碼營
Java的容器
定義好Post類之后,現(xiàn)在需要對博客文章進行管理。我們可以定義一個PostRepository類,通過PostRepository可以做以下操作:
- 創(chuàng)建博客
- 刪除博客
- 獲取一篇博客的內(nèi)容
- 獲取博客列表
我們已經(jīng)有面向?qū)ο缶幊痰慕?jīng)驗了,我們可以給Repository增加四個方法:
package com.tianmaying.repository;import com.tianmaying.domain.Post;public class PostRepository {public static void add(Post post) {}public static Post getPostById(long id) {return null;}public static void remove(long id) {}public static ArrayList<Post> getAll() {return null;} }上面我們定義了四個靜態(tài)成員方法,我們剛剛講過static修飾方法的含義,現(xiàn)在馬上就用到了。你現(xiàn)在可能對getAll()方法返回的ArrayList<Post>還有點疑惑,沒關(guān)系,我們馬上就要講到。
先來考慮一個問題,這個PostRepository里面應(yīng)該包含什么變量呢? 我們很容易想到就是一組博客。在Java中,我們可以通過數(shù)組將一組對象組織在一起,因此我們馬上可以想到定義一個Post的數(shù)組。
但是數(shù)組的尺寸是固定的,通常情況下程序總是在運行時根據(jù)條件來創(chuàng)建對象,我們可能無法預(yù)知將要創(chuàng)建對象的個數(shù),甚至是具體的類型。比如PostRepository中保存多少Blog對象我們事先是不知道的。
這時我們就需要Java的集合(Collection)類了。我們通常也稱集合為容器,因為它們可以幫我們方便地組織和管理一組對象。
所以我們可以給PostRepository類增加一個靜態(tài)成員變量:
public class PostRepository {private static posts = new ArrayList<Post>();... }這里ArrayList就是Java提供給我們使用的一個集合類,用以保存一個元素序列,并且可以進行元素的訪問、插入和刪除等操作。
ArrayList<Post>是一種泛型的寫法。泛型就是參數(shù)化類型,即ArrayList所操作的數(shù)據(jù)類型通過一個類型參數(shù)指定。ArrayList這個容器中可以保存任何類型的變量,而且這些對象訪問、插入和刪除的邏輯也是相同的。比如,如果我們希望ArrayList中存放一組整數(shù)的話,我們就可以聲明List<Integer>類型的變量。
在Java 7和Java 8中,編譯器能夠根據(jù)變量聲明時的泛型類型自動推斷出實例化所用的泛型類型。
ArrayList<Post> post1 = new ArrayList<Post>(); ArrayList<Post> post2 = new ArrayList<>();post2的初始化就沒有指定ArrayList中的泛型類型,編譯器可以推導(dǎo)出來。
List的使用
ArrayList提供了一系列操作元素序列的方法。下面我們使用ArrayList來實現(xiàn)PostRepository的四個方法。
package com.tianmaying.repository;import java.util.ArrayList; import java.util.List;import com.tianmaying.domain.Post;public class PostRepository {private static ArrayList<Post> posts = new ArrayList<Post>();public static void add(Post post) {posts.add(post);}public static Post getPostById(long id) {for (Post post : posts) {if (post.getId() == id) {return post;}}return null;}public static void remove(long id) {for (Post post: posts) {if (post.getId() == id) {posts.remove(post); return;}}}public static ArrayList<Post> getAll() {return posts;} }我們看到ArrayList的用法很簡單,可以通過add方法增加元素,通過remove方法刪除元素。
遍歷ArrayList的方法是一種特殊的for循環(huán),遍歷Java容器中的元素都可以使用這種方法。
我們也可以使用迭代器Iterator類來完成遍歷。Iterator主要有兩個方法,基于這兩個方法就能進行遍歷操作:
- next()方法來獲取序列的下一個元素
- hasNext()檢查序列中是否還有元素
使用Iterator實現(xiàn)的代碼如下:
public static void remove(long id) {Iterator<Post> iterator = posts.iterator();while (iterator.hasNext()) {Post post = iterator.next();if (post.getId() == id) {posts.remove(post); return;}} }與ArrayList類似的一種容器是LinkedList,它們都是List接口的實現(xiàn)。接口的概念我們后面會講,現(xiàn)在你只需要知道操作ArrayList和操作LinkedList的方式是完全一樣的,只不過它們內(nèi)部的實現(xiàn)機制不一樣。
這兩者的主要不同在于:
- ArrayList:通過下標(biāo)隨機訪問元素快,但是插入、刪除元素較慢
- LinkedList:插入、刪除和移動元素快,但是通過下標(biāo)隨機訪問元素性能較低
如果你學(xué)過數(shù)據(jù)結(jié)構(gòu),就是知道ArrayList是基于數(shù)組實現(xiàn)的,而LinkedList是基于鏈表實現(xiàn)的。這兩種數(shù)據(jù)結(jié)構(gòu)的特點決定了這兩個容器的不同之處。
Map
Map故名思議,就是映射,可以將一個對象映射到另一個對象。每一組映射作為一個<鍵,值>對保存在Map容器中。Map和List一樣是一種接口,它的實現(xiàn)HashMap類,是我們最常使用的一種容器。
我們回顧getPostById這個方法的實現(xiàn):
public static Post getPostById(long id) {for (Post post : posts) {if (post.getId() == id) {return post;}}return null; }每次都要經(jīng)過一次遍歷,經(jīng)過比較才能找到id對應(yīng)的博客。如果能夠把作為一個鍵值對,那么通過id取出一篇博客就更加快速和方便。現(xiàn)在基于Map來實現(xiàn)博客管理功能,我們新建另外一個類PostRepositoryByMap:
package com.tianmaying.repository;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;import com.tianmaying.domain.Post;public class PostRepositoryByMap {private static Map<Long, Post> postsMap = new HashMap<Long, Post>();public static void add(Post post) {postsMap.put(post.getId(), post);}public static Post getPostById(long id) { return postsMap.get(id);}public static void remove(long id) {postsMap.remove(id);}public static List<Post> `addAll`方法() {List<Post> posts = new ArrayList<>(); posts.addAll(postsMap.values());return posts;}} `Map具有兩個泛型參數(shù),第一個是鍵的類型,第二個是值的類型。類型不能是原生類型,必須是引用類型,因此這里第一個類型是long的包裝類Long。
使用Map之后,查找和刪除博客的實現(xiàn)就非常簡單了:
- put方法可以增加一個鍵值對
- get方法就能根據(jù)鍵獲取到值
- remove方法可以刪除鍵對應(yīng)的元素
Java編譯器會在需要時自動幫我們進行原生數(shù)據(jù)類型和包裝類之間進行轉(zhuǎn)換,比如我們postMap.remove(id);這條語句傳入的是long原生數(shù)據(jù)類型,Java編譯器知道此時應(yīng)該傳入的是Long,會自動幫我們做這個轉(zhuǎn)換。
我們可以獲取鍵、值或鍵值對的集合,分別使用keySet, values以及entrySet。getAll方法就通過postsMap.values()獲取所有的值,這里就是所有的Blog對象。
注意這里調(diào)用了一個addAll方法,這個方法是所有容器都有的一個方法,可以把另外一個容器中的元素加入其中。
我們可以這樣遍歷一個Map:
for (Map.Entry<Long, Post> postEntry : postMap.entrySet()) {Long id = postEntry.getKey();Post post = postEntry.getValue();// 在遍歷中操作每一個post... }如果PostRepositoryByMap的getAll()方法不使用addAll方法,而通過遍歷的方式逐個將博客對象加入到一個List中,如何實現(xiàn)呢? 你可以嘗試一下。
作者:David
鏈接:https://zhuanlan.zhihu.com/p/20676879
來源:知乎
總結(jié)
以上是生活随笔為你收集整理的Java集合的使用:List与Map的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你必须学会的Git入门基本操作
- 下一篇: Java时间日期格式转换