Java 集合深入理解(3):Collection

拭心發表於2016-10-10

點選檢視 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~


今天心情有點粉,來學學 Collection 吧!

什麼是集合?

  • 集合,或者叫容器,是一個包含多個元素的物件;
  • 集合可以對資料進行儲存,檢索,操作;
  • 它們可以把許多個體組織成一個整體:
    • 比如一副撲克牌(許多牌組成的集合);
    • 比如一個電話本(許多姓名和號碼的對映)。

什麼是集合框架?

集合框架是一個代表、操作集合的統一架構。所有的集合框架都包含以下幾點:

  • 介面:表示集合的抽象資料型別。介面允許我們操作集合時不必關注具體實現,從而達到“多型”。在物件導向程式語言中,介面通常用來形成規範。
  • 實現類:集合介面的具體實現,是重用性很高的資料結構。
  • 演算法:用來根據需要對實體類中的物件進行計算,比如查詢,排序。
    • 同一種演算法可以對不同的集合實現類進行計算,這是利用了“多型”。
    • 重用性很高。

不僅 Java,其他語言也有一些集合框架,比如 C艹 的 STL(標準模板庫),Smalltalk 的集合層次結構。不同於他們陡峭的學習曲線,Java 集合框架設計的更加合理,學習起來更加輕鬆。

使用集合框架有什麼好處呢?

使用 Java 集合框架能有以下幾點好處:

  • 編碼更輕鬆:Java 集合框架為我們提供了方便使用的資料結構和演算法,讓我們不用從頭造輪子,直接操心上層業務就好了。
  • 程式碼質量更上一層樓:Java 集合框架經過幾次升級迭代,資料結構和演算法的效能已經優化地很棒了。由於是針對介面程式設計,不同實現類可以輕易互相替換。這麼優雅的設計,省下你自己磨練多少工夫,恩?!
  • 減少學習新 API 的成本:過去每個集合 API 下還有子 API 來對 API 進行操作,你得學好幾層才能知道怎麼使用,而且還容易出錯。現在好了!有了標準的 Java 集合框架,每個 API 都繼承自己頂層 API,只負責具體實現,一口氣學 5 個集合,不費勁!
  • 照貓畫虎也容易多了:由於頂層介面已經把基礎方法都定義好了,你只要實現介面,把具體實現方法填好,再也不用操心架構設計。

Java 集合框架主要結構圖

這裡寫圖片描述

如上圖所示,Java 的集合主要按兩種介面分類:Collection, Map.

Collection 介面

Collection 作為集合的一個根介面,定義了一組物件和它的子類需要實現的 15 個方法:

這裡寫圖片描述

對集合的基礎操作,比如 :

  • int size()
    • 獲取元素個數
    • boolean isEmpty()
    • 是否個數為 0
    • boolean contains(Object element)
    • 是否包含指定元素
    • boolean add(E element)
    • 新增元素,成功時返回 true
    • boolean remove(Object element)
    • 刪除元素,成功時返回 true
    • Iterator<E> iterator()
    • 獲取迭代器

還有一些操作整個集合的方法,比如 :

  • boolean containsAll(Collection<?> c)
    • 是否包含指定集合 c 的全部元素
  • boolean addAll(Collection<? extends E> c)
    • 新增集合 c 中所有的元素到本集合中,如果集合有改變就返回 true
  • boolean removeAll(Collection<?> c)
    • 刪除本集合中和 c 集合中一致的元素,如果集合有改變就返回 true
  • boolean retainAll(Collection<?> c)
    • 保留本集合中 c 集合中兩者共有的,如果集合有改變就返回 true
  • void clear()
    • 刪除所有元素

還有對陣列操作的方法:

  • Object[] toArray()
    • 返回一個包含集合中所有元素的陣列
  • <T> T[] toArray(T[] a)
    • 返回一個包含集合中所有元素的陣列,執行時根據集合元素的型別指定陣列的型別

在 JDK 8 以後,Collection 介面還提供了從集合獲取連續的或者並行流:

  • Stream<E> stream()
  • Stream<E> parallelStream()

點選這裡瞭解流 Stream.

遍歷 Collection 的幾種方式:

  1. for-each語法

    Collection<Person> persons = new ArrayList<Person>();
    for (Person person : persons) { 
        System.out.println(person.name);  
    }  
    
  2. 使用 Iterator 迭代器

    Collection<Person> persons = new ArrayList<Person>();
    Iterator iterator = persons.iterator();
    while (iterator.hasNext) { 
        System.out.println(iterator.next);  
    }  
    
  3. 使用 aggregate operations 聚合操作

    Collection<Person> persons = new ArrayList<Person>();
    persons
        .stream()
        .forEach(new Consumer<Person>() {  
            @Override  
            public void accept(Person person) {  
                System.out.println(person.name);  
            }  
    }); 
    

Aggregate Operations 聚合操作

在 JDK 8 以後,推薦使用聚合操作對一個集合進行操作。聚合操作通常和 lambda 表示式結合使用,讓程式碼看起來更簡潔(因此可能更難理解)。下面舉幾個簡單的栗子:

1.使用流來遍歷一個 ShapesCollection,然後輸出紅色的元素:

myShapesCollection.stream()
    .filter(e -> e.getColor() == Color.RED)
    .forEach(e -> System.out.println(e.getName()));

2.你還可以獲取一個並行流(parallelStream),當集合元素很多時使用併發可以提高效率:

myShapesCollection.parallelStream()
    .filter(e -> e.getColor() == Color.RED)
    .forEach(e -> System.out.println(e.getName()));                         

3.聚合操作還有很多操作集合的方法,比如說你想把 Collection 中的元素都轉成 String 物件,然後把它們 連起來:

String joined = elements.stream()
    .map(Object::toString)
    .collect(Collectors.joining(", "));

看起來是不是非常簡潔呢!

聚合操作還有很多功能,這裡僅做介紹,想要了解更多可以檢視Aggregate Operations 官方指引

Iterator 迭代器

Java 集合解析:IteratorJava 集合解析:ListIterator 我介紹了 Collection 的迭代器 Iterator 以及用於 List 的迭代器 ListIterator。

結合 Collection 和 Iterator 可以實現一些複用性很強的方法,比如這樣:

public static void filter(Collection<?> c) {
    for (Iterator<?> it = c.iterator(); it.hasNext(); )
        if (!condition(it.next()))
            it.remove();
}

這個 filter 方法是多型的,可以用於所有 Collection 的子類、實現類。 這個例子說明了使用 Java 集合框架我們可以很隨便就寫出 “優雅,可擴充,複用性強” 的程式碼~

總結

Collection 介面是類集框架的基礎之一。

它建立所有類集都將擁有的 15 個核心方法。

因為幾乎所有集合類集都實現了 Collection介面,所以熟悉它對於清楚地理解框架是必要的。

接下來將逐步瞭解集合框架的各個子介面及實現類。

感謝 密哥 提醒,parallel 應該是並行,而不是併發。

併發與並行的概念區別還是挺大的。

並行”是指無論從微觀還是巨集觀,二者都是一起執行的,就好像兩個人各拿一把鐵杴在挖坑,一小時後,每人一個大坑。
而“併發”在微觀上不是同時執行的,只是把時間分成若干段,使多個程式快速交替的執行,從巨集觀外來看,好像是這些程式都在執行,這就好像兩個人用同一把鐵杴,輪流挖坑,一小時後,兩個人各挖一個小一點的坑,要想挖兩個大一點得坑,一定會用兩個小時。
從以上本質不難看出,“併發”執行,在多個程式存在資源衝突時,並沒有從根本提高執行效率。
http://zhidao.baidu.com/link?url=1L6YSAULAhjLH4ZYfO0yCbKlvo8DJeQMtCmCLKYpENStbpxNDiFCwaJf4iZaNDr7cho37GctXOddek3LhrO3_K

這裡 看到的一幅生動形象圖:

這裡寫圖片描述

Thanks

https://docs.oracle.com/javase/tutorial/collections/intro/index.html

https://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html

http://joearms.github.io/2013/04/05/concurrent-and-parallel-programming.html

相關文章