JAVA集合系列(2):Collection和Iterator接口

前言

首先,我們對Collection進行說明。下面先看看下JDK文檔中對於Collection集合的一些說明:

public interface Collection<E> extends Iterable<E>

集合層次結構中的根界面 。
集合表示一組被稱爲其元素的對象。一些集合允許重複元素,而其他集合不允許。有些被命令和其他無序。

JDK不提供此接口的任何直接實現:它提供了更具體的子接口的實現,如Set和List。
該界面通常用於傳遞集合,並在需要最大的通用性的情況下對其進行操作。 
包或多重集(可能包含重複元素的無序集合)應直接實現此接口。

所有通用的Collection實現類,應提供兩個"標準"構造函數:

  • 一個void(無參數)構造函數,它創建一個空集合,
  • 一個構造函數, Collection ,它創建一個與其參數相同的元素的新集合。 

實際上,後一個構造函數允許用戶複製任何集合,生成所需實現類型的等效集合。 沒有辦法強制執行此約定(因爲接口不能包含構造函數),而是所有Java平臺庫中的通用Collection實現。

實現要求:

  • 默認方法實現(繼承或其他)不應用任何同步協議。 如果Collection實現具有特定的同步協議,那麼它必須覆蓋默認實現以應用該協議。

1、Collection接口的方法摘要

OK,我們來看一下Collection接口的一些方法摘要。

Collection接口中的方法

返回值類型

方法

描述

boolean add(E e) 確保此集合包含指定的元素(可選操作)。 
boolean addAll(Collection<? extends E> c)  將指定集合中的所有元素添加到此集合(可選操作)。
void clear()  從此集合中刪除所有元素(可選操作)。  
boolean contains(Object o) 如果此集合包含指定的元素,則返回 true。
boolean containsAll(Collection<?> c) 如果此集合包含指定 集合中的所有元素,則返回true。
boolean equals(Object o) 將指定的對象與此集合進行比較以獲得相等性。
int hashCode() 返回此集合的哈希碼值。
boolean isEmpty() 如果此集合不包含元素,則返回 true 。
Iterator<E> iterator() 返回此集合中的元素的迭代器。
default Stream<E> parallelStream()  返回可能並行的 Stream與此集合作爲其來源。  
boolean remove(Object o) 從該集合中刪除指定元素的單個實例(如果存在)(可選操作)。 
boolean removeAll(Collection<?> c) 刪除指定集合中包含的所有此集合的元素(可選操作)。  
default boolean removeIf(Predicate<? super E> filter) 刪除滿足給定謂詞的此集合的所有元素。  
boolean retainAll(Collection<?> c) 僅保留此集合中包含在指定集合中的元素(可選操作)。 
int size() 返回此集合中的元素數。
default Spliterator<E> spliterator() 創建一個Spliterator在這個集合中的元素。  
default Stream<E> stream() 返回以此集合作爲源的順序 Stream 。  
Object[] toArray() 返回一個包含此集合中所有元素的數組。  
<T> T[] toArray(T[] a)  返回包含此集合中所有元素的數組; 返回的數組的運行時類型是指定數組的運行時類型。  

 

 

2、Collection接口的方法詳細信息

接下來,通過幾個demo測試類來了解下Collection中的這些方法詳細信息。

【1】int size();

作用描述:返回此集合中的元素數。如果此collection包含超過Integer.MAX_VALUE個元素,則返回Integer.MAX_VALUE 。 

返回結果:此集合中的元素數 

測試程序:

@Test
public void test_size(){
    Collection<String> collection = new ArrayList<>();
    collection.add("a");
    collection.add("b");
    collection.add("c");
    collection.add("d");
    int size = collection.size();
    System.out.println("集合中元素的個數:" + size);
}

測試結果:

集合中元素的個數:4

【2】 boolean isEmpty();

作用描述:判斷集合是否爲空,如果爲空,則返回 true;反之,則返回false。

返回結果:true/false

測試程序:

@Test
public void test_isEmpty(){
    Collection<String> collection = new ArrayList<>();
    collection.add("a");
    collection.add("b");
    collection.add("c");
    boolean isEmpty = collection.isEmpty();
    System.out.println("集合是否爲空:" + isEmpty);
}

測試結果:

集合是否爲空:false

【3】 boolean contains(Object o);

作用描述:判斷集合是否包含指定元素,如果包含,則返回 true;反之,則返回false。

返回結果:true/false

測試程序:

@Test
public void test_isEmpty(){
    Collection<String> collection = new ArrayList<>();
    collection.add("a");
    collection.add("b");
    collection.add("c");
    boolean isContains = collection.contains("a");
    System.out.println("集合是否包含元素a:" + isContains);
}

測試結果:

集合是否包含元素a:true

【4】 Iteratble<E> iterator();

作用描述:返回此集合中的元素的迭代器。 沒有關於元素返回順序的保證(除非這個集合是提供保證的某個類的實例)。 

返回結果:一個 Iterator在這個集合中的元素 。

測試程序:

@Test
public void test_iterator() {
    Collection<String> collection = new ArrayList<>();
    collection.add("a");
    collection.add("b");
    collection.add("c");

    Iterator<String> iterator = collection.iterator();
    while (iterator.hasNext()) {
        String next = iterator.next();
        System.out.println("迭代器遍歷出來的集合元素:" + next);
    }
}

測試結果:

迭代器遍歷出來的集合元素:a
迭代器遍歷出來的集合元素:b
迭代器遍歷出來的集合元素:c

【5】 Object[] toArray();

作用描述:返回一個包含此集合中所有元素的數組。如果此集合對其迭代器返回的元素的順序做出任何保證,則此方法必須以相同的順序返回元素。 返回的數組將是“安全的”,因爲該集合不保留對它的引用。(換句話說,這個方法必須分配一個新的數組,即使這個集合是由數組支持的)。因此,調用者可以自由地修改返回的數組。此方法充當基於陣列和基於集合的API之間的橋樑。 

返回結果:一個包含此集合中所有元素的數組

測試程序:

@Test
public void test_toArray() {
    Collection<String> collection = new ArrayList<>();
    collection.add("a");
    collection.add("b");
    collection.add("c");
    System.out.println("集合元素:" + collection);

    Object[] objects = collection.toArray();
    for (int i = 0; i<objects.length;i++){
        System.out.println("數組元素:" + objects[i].toString());
    }
}

測試結果:

集合元素:[a, b, c]
數組元素:a
數組元素:b
數組元素:c

【6】 1-boolean remove();   2-void clear();

作用描述:1-移除集合中的元素;2-清空集合 

返回結果:1-true/false;2-void;

測試程序:

@Test
public void test_removeAndClear(){
    Collection<String> collection = new ArrayList<>();
    collection.add("a");
    collection.add("b");
    collection.add("c");
    System.out.println("集合元素:" + collection);

    boolean remove = collection.remove("c");
    System.out.println("移除元素a後的新集合:" + collection);

    collection.clear();
    System.out.println("清空後的集合:" + collection);
}

測試結果:

集合元素:[a, b, c]
移除元素a後的新集合:[a, b]
清空集合:[]

3、使用Lambda表達式遍歷集合

Java 8爲Iterator接口新增了一個foreach(Consumer action)默認方法,該方法所需參數時一個函數式接口,而Iterator接口是Collection接口的父類接口,因此Collection集合也可以直接調用該方法。

當程序調用Iterable的foreach(Customer action)遍歷集合元素時,程序會依次將集合元素傳給Customer的accept(T t)方法。正因爲Cosumer是函數式接口,因此可以使用Lambada表達式來遍歷集合元素。

使用Lambda表達式來表裏集合元素:

@Test
public void fun(){
    Collection collection = new HashSet<>();
    collection.add("hello");
    collection.add("world");
    collection.add("!");
    //foreach遍歷集合元素
    collection.forEach(Object -> System.out.println("迭代集合元素:" +Object));
}

測試結果:

迭代元素:hello
迭代元素:world
迭代元素:!

調用Iterable的foreach默認方法來遍歷集合元素,傳遞給該方法的參數是一個Lambda表達式,該Lambda表達式的目標類型是Cosumer。foreach()方法會自動將集合元素逐個地傳遞給Lambda表達式的形參,這樣Lambda表達式的代碼體即可遍歷到集合元素了。


4、使用Java8增強的Iterator遍歷集合

Iterator接口即Java集合框架的成員,但它與Collection系列、Map系列的集合不同:

  • Collection系列集合、Map系列集合主要用於裝載其它對象;
  • 而Iterator則主要用於遍歷(迭代訪問)Collection集合中的元素。

Iterator接口裏定義的方法如下表:

Iterator接口裏的方法方法說明
方法 描述
boolean hasNext() 如果被迭代的集合元素還沒有被遍歷完,則返回true
Object next() 返回集合的下一個元素
void remove() 刪除集合裏上一次next方法返回的元素
void forEachRemaining(Consumer action) Java 8新增的默認方法,該方法可使用Lambda表達式來遍歷集合元素

接下來,使用Iteratior接口來遍歷集合元素:

@Test
public void fun2(){
    Collection collection = new ArrayList<>();
    collection.add("hello");
    collection.add("world");
    collection.add("!");
    System.out.println("集合元素:" + collection);

    //獲取collection集合對應的迭代器
    Iterator iterator = collection.iterator();
    while (iterator.hasNext()) {
        //返回集合裏的下一個元素
        String next = (String) iterator.next();

        if (next.contains("hello")) {
            //從集合中刪除上一次next()方法返回的元素
            iterator.remove();
        }

        //對next賦值,不會改變集合元素本身
        next = "OK";
    }
    System.out.println("新的集合元素:" + collection);
}

測試結果:

集合元素:[hello, world, !]
新的集合元素:[world, !]

注意:

  • Iterator 必須依附於Collection對象,若有一個Iterator對象,則必然有一個與之關聯的Collection對象。
  • Iterator提供了兩個方法來迭代訪問Collection集合裏的元素,並可以通過remove()方法來刪除集合中上一次next()方法返回的集合元素。
  • Iterator迭代訪問Collection集合元素時,Collection集合裏的元素不能被改變,只有通過Iterator的reomve()方法刪除上一次next()方法返回的集合元素纔可以;否則將拋ConcurrentModificationException異常。

5、使用Lambda表達式遍歷Iterator

Java 8爲Iterator新增了一個forEachRemaining(Consumer action)方法,該方法所需的Consumer參數同樣也是函數式接口。

當程序調用Iterator的forEachRemaining(Consumer action)遍歷集合元素時,程序會依次將集合元素傳給Consumer的accept(T t)方法。

使用Lambda表達式來遍歷集合元素:

/**
 * 使用Lambda表達式遍歷Iterator
 */
@Test
public void run2() {
    Collection<String> col = new ArrayList<>();
    col.add("hello");
    col.add("world");
    col.add("!");

    Iterator<String> iterator = col.iterator();
    iterator.forEachRemaining(obj-> System.out.println("迭代集合元素" + obj));
}

上面 iterator調用forEachRemaining(Consumer action)遍歷集合元素,傳遞給該方法的參數是一個Lambda表達式,該Lambda表達式的目標類型是Consumer。


6、使用foreach循環遍歷集合元素

除了可以使用Iterator接口迭代訪問Collection集合裏的元素,使用Java 5提供的foreach循環迭代訪問集合的元素也很便捷。

舉個栗子:

@Test
public void run4() {
    Collection collection = new ArrayList<>();
    collection.add("hello");
    collection.add("world");
    collection.add("!");
    System.out.println("集合元素:" + collection);

    for (Object value : collection) {
        System.out.println("foreach遍歷集合元素:" + value.toString());
        //循環遍歷集合時,不能修改集合元素,拋異常:java.util.ConcurrentModificationException
        //collection.remove("hello");
    }
}

測試結果:

集合元素:[hello, world, !]
foreach遍歷集合元素:hello
foreach遍歷集合元素:world
foreach遍歷集合元素:!

與Iterator接口迭代訪問集合元素類似的是,foreach循環中的迭代變量也不是集合元素本身,系統只是依次把集合元素的值賦給迭代變量,因此在foreach循環中修改迭代變量的值也沒有任何實際意義。

注意:foreach遍歷集合元素時,該集合不能被改變,否則將拋ConcurrentModificationException異常。


願你就像早晨八九點鐘的太陽,活力十足,永遠年輕。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章