Java中的集合Collection、Iterator和Foreach用法(一)


1.Java集合概述

  在編程中,常常需要集中存放多個數據。當然我們可以使用數組來保存多個對象。但數組長度不可變化,一旦在初始化時指定了數組長度,則這個數組長度是不可變的,如果需要保存個數變化的數據,數組就顯得無能為力了;而且數組無法保存具有映射關系的數據,如成績表:語文-80,數學-90,這種數據看上去像兩個數組,但這兩個數組的元素之間有一定的關聯關系。

  為了保存數量不確定的數據,以及保存具有映射關系的數據,Java提供了集合類。集合類主要負責保存、盛裝其他數據,因此集合類也被稱為容器類。所有集合類都位於Java.util包下

  集合類和數組不一樣,數組既可以是基本類型的值,也可以是對象(實際上保存的是對象的引用變量);而集合里只能保存對象,例如不能保存int、只能保存integer

  Java的集合類主要有兩個接口派生而出:CollectionMap,Collection和Map是Java集合框架的根接口,這兩個接口又包含了一些子接口和實現類

  如下圖所示Collection體系的繼承樹:

  

  如上圖所示顯示了Collection體系里的集合,Set、List接口是Collection接口派生的兩個子接口,它們分別代表了無序集合、有序集合;Queue[kju:]是Java提供的隊列(隊列特點:先進先出)實現,有點類似於List。

  如下圖所示Map體系的繼承樹:

 

  如上圖所示顯示了Map接口的眾多實現類,這些實現類在功能、用法上存在一定的差異,但他們都有一個功能特征:Map保存的每項數據都是key-value對,也就是由key和value兩個值組成。就向前  面簡紹的成績單:語文-80,數學-90,每項成績都是由2個值組成:科目名和成績;Map里的key是不可重復的,key用於標識集合里每項數據,如果需要查詢Map中的數據時,總是根據Map的key來獲取

  根據上兩圖,我們可以把Java的所有集合分成三大類,其中Set集合類似於一個罐子,把一個對象添加到Set集合時,Set集合無法記住添加這個元素的順序,所以Set里的元素不能重復(否則系統無法准確識別這個元素);List集合非常像一個數組,它可以記住每次添加元素的順序,只是List的長度可變。Map集合也像一個罐子,只是它里面的每項數據都由兩個值組成。

  如下圖所示顯示了三種集合的示意圖:

   從上圖可以看出,如果訪問List集合中的元素,可以直接根據元素的索引來訪問;如果需要訪問Map集合中的元素,可以根據每項元素的key來訪問其value;如果希望訪問Set集合中的元素,則只能根據元素本身來訪問(這也是Set集合里的元素不容許重復的原因)。

  對於Set、List和Map三種集合,最常用的實現類分別為HashSet、ArrayList和HashMap,這三個實現類都沒有實現並發控制,是屬於線程不安全的。

2.Collection和Iterator接口

  • Collection接口

   Collection接口是List、Set和Queue接口的父接口,該接口中定義的方法既可用於操作Set集合,也可用於操作List和Queue集合。Collection中定義了如下操作集合元素的方法:

    1. boolean add(Object o);  該方法用於向集合里添加一個元素。如果集合對象被添加操作改變了則返回true。 
    2. boolean addAll(Collection c);  該方法把集合c里面的所有元素添加到指定集合里。如果集合對象唄添加操作改變了則返回true。
    3. void clear(); 清楚集合里的所有元素,將集合長度變為0。
    4. boolean contains(Object o);  返回集合里是否包含指定元素。
    5. boolean containsAll(Collection c);  返回集合里是否包含集合c里面的所有元素。
    6. boolean isEmpty();   返回集合是否為空。當集合長度為0時,返回true,否則返回false。
    7. Iterator iterator();    返回一個Iterator對象,用於遍歷集合里的元素。
    8. boolean remove(Object o);   刪除集合中指定元素o,當集合中包含一個或多個元素o時,這些元素將被刪除,該方法將返回true。 
    9. boolean removeAll(Collection c);  從集合中刪除集合c里包含的所有元素(相當於調用該方法的集合減集合c),如果刪除了一個或一個以上的元素,該方法返回true。
    10. boolean retainAll(Collection c); 從集合中刪除集合c里不包含的所有元素(相當於取得把調用該方法的集合變成該集合和集合c的交集),如果該操作改變了調用該方法的集合,該方法返回true。
    11. int size();   該方法返回集合元素里的個數。
    12. Object[] toArray();  該方法把集合轉換成一個數組,所有集合元素變成對應的數組元素。
  • Iterator接口

  Iterator接口也是Java集合框架的成員,但它與Collection系列、Map系列的集合不一樣:Collection系列集合、Map系列集合主要用於盛裝其他對象,而Iterator則主要用於遍歷(即迭代訪問)Collection集合中的元素,Iterator對象也被稱為迭代器。

  Iterator接口隱藏了各種Collection實現類的底層細節,向應用程序提供了遍歷Collection集合元素的統一編程接口,Iterator接口里定義了如下三個方法:

    1. boolean hasNext();   如果被迭代的集合元素還沒有被遍歷,則返回true。
    2. Object next();    返回集合里下一個元素。
    3. void remove();   刪除集合里上一次next返回的元素。
class test{
    public static void main(String[] args){
        Collection books = new HashSet(); 
        books.add("語文");
        books.add("數學");
        books.add("英語");
        //打印結果為[語文, 英語, 數學]
        System.out.println(books);
        Iterator it = books.iterator();
        while(it.hasNext()){
            String book= (String)it.next();
            if("語文".equals(book)){
                it.remove();
            }
            //對book變量賦值,不會改變集合元素本身
            book = "測試字段";
           
        }
        //打印結果為[英語, 數學]
        System.out.println(books);
    }
}

   上面代碼對迭代變量book進行賦值,但當我們再次輸出books集合時,看到集合里的元素沒有任何的改變。這就可以得出一個結論:當使用Iterator對集合元素進行迭代時,Iterator並不是把集合元素本身傳給了迭代變量,二是把集合元素的值傳給了迭代變量,所以修改迭代變量的值對集合本身沒有任何改變。如下原理:

public class test{
    public static void main(String[] args){
        String str = "zhangsan";
        //打印結果為zhangsan
        System.out.println(str);
        updateString(str);
        //打印結果還是zhangsan
        System.out.println(str);
    }
    
    public static void updateString(String str2){
        //這個就相當於你在Iterator里面傳的值,所以修改變量str2的值對str本身沒有任何變化
        str2 = "lisi";
    }
}

   但是當傳遞的是對象時,則可以修改傳入對象的值如下:

public class test{
    public static void main(String[] args){
        Person p = new Person();
            p.setId(1);
            p.setName("zhangsan");
        //打印結果為id = 1 name = zhangsan
        System.out.println(p);
        updatePerson(p);
        //打印結果為id = 2 name = lisi
        System.out.println(p);

    }
    
    public static void updatePerson(Person p1){
        //這個就相當於你在Iterator里面傳的是對象,它給你傳的是地址,所以你修改p1,就相當於修改了p的值
        p1.setId(2);
        p1.setName("lisi");
    }
}

class Person{
    
    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "id = " + id + " name = " + name;
    }
}

  當使用Iterator來迭代訪問Collection集合元素時,Collection集合里的元素不能被改變,只有通過Iterator的remove方法來刪除上一次next方法返回的集合元素才可以。否則將會引發Java.util.ConcurrentModificationException異常。如下:

 

public class Test {
    
    public static void main(String[] args){
        Collection books = new HashSet();
        books.add("語文");
        books.add("數學");
        books.add("英語");
        Iterator it  =  books.iterator();
        while(it.hasNext()){
            String book = (String)it.next();
            if(book.equals("英語")){
                //這樣做就會拋Java.util.ConcurrentModificationException
                books.remove(book);
            }
        }
    }
}

 

  • 使用foreach循環遍歷集合元素

  除了可以使用Iterator類迭代訪問Collection集合里的元素外,也可以使用foreach循環來迭代訪問集合元素,而且更加便捷如下:

public class Test {
    
    public static void main(String[] args){
        Collection books = new HashSet();
        books.add("語文");
        books.add("數學");
        books.add("英語");
        for(Object o : books){
            String book = (String)o;
            if(book.equals("語文")){
                //這行代碼將會引發java.util.ConcurrentModificationException異常
                //books.remove(book);
            }
            System.out.println(o);
        }
    }
}

 

   如上所示,同樣,當使用foreach循環迭代訪問集合元素時,該集合也不能被改變,否則將引發ConcurrentModificationException異常。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM