Java基礎(chǔ)進(jìn)階 ?集合框架

今日任務(wù)

1、集合框架繼承體系(理解)
2、Collection接口介紹(掌握常用Collection方法)
3、迭代器(掌握)
4、集合的細(xì)節(jié)
5、集合使用的步驟

1、集合框架的繼承體系

集合是用來存儲數(shù)據(jù)的一類容器,但是在使用集合存儲數(shù)據(jù)時,也會有不同的存儲需求。例:存儲的數(shù)據(jù)不能有重復(fù)的、存儲的數(shù)據(jù)可以自動排序、存儲的數(shù)據(jù)無序。針對不同的存儲需求,java設(shè)計了存儲不同需求的集合對象。這些針對不同需求的集合對象,雖然存儲方法式不同,但是都具有共性的功能:比如:增、刪、改、查(CRUD create read update delete)等操作。所以我們把共性的操作向上抽取,最終形成了一個集合框架的繼承體系結(jié)構(gòu)。

既然有上述的共性的規(guī)律,于是Java就把這些最基本的規(guī)律抽取到了一個接口中。其中一個頂級接口就是:Collection接口。

在集合框架體系中用接口來定義所有集合操作的共性規(guī)則。

集合體系框架從JDK1.2才開始存在。早期有集合,但是它們沒有形成一個體系。

集合框架的繼承體系如下圖所示:

說明:

1)Collection是這個體系的頂級接口;

2)Collection中定義了所有集合子類的共性操作;

3)我們先從Collection接口開始學(xué)習(xí),將Collection中的函數(shù)學(xué)完之后,實現(xiàn)類都可以直接使用,最后我們在去學(xué)習(xí)子類特有的函數(shù)就可以了;

4)通過查閱API得知Collection、List、Set接口下面不是只有如上圖所示的子類或者子接口,但是我們在開發(fā)中主要使用這些集合;

2、集合Collection接口

2.1、Collection接口介紹

Collection接口:它是集合的最頂層接口,它中規(guī)定了所有集合中的最基本的操作規(guī)律。而Java中提供的所有集合容器都保存在java.util包下。

image

Collection接口是集合的頂層接口,它下面有子接口或者間接的實現(xiàn)類,而具體的實現(xiàn)類中有些可以保存重復(fù)元素,有些不能保存重復(fù)元素,有些可以保證數(shù)據(jù)有序,一些則無序。

說明:在學(xué)習(xí)集合框架的時候,遇到的所有E類型,全部理解成Object類型。

2.2、Collection中的方法介紹

2.2.1、添加方法

image

說明:把指定的引用類型數(shù)據(jù),添加到集合中。添加成功則返回true。

我們知道Collection是接口,它不能new對象。而Collection中定義的是所有集合共性的操作規(guī)律。那么我們就可以隨便找個Collection的實現(xiàn)類,例如ArrayList類。這樣就可以使用多態(tài)的方式來操作集合。

代碼舉例:Collection coll=new ArrayList();//這里發(fā)生多態(tài)

步驟和分析:

1)使用new關(guān)鍵字創(chuàng)建集合類ArrayList的對象,對象的類型是接口Collection;

2)使用集合對象coll調(diào)用add()函數(shù)給集合中添加不同的數(shù)據(jù);


package cn.xuexi.demo1;

import java.util.ArrayList;

import java.util.Collection;

import cn.xuexi.sh.demo.Student;

/*

* Collection接口中add方法的演示

*/

public class CollectionAddDemo {

    public static void main(String[] args) {
        /*
        *由于Collection是接口,所以不能創(chuàng)建Collection接口的對象,
        *但是我們可以使用new關(guān)鍵字創(chuàng)建Collection接口下面的任意一個類的對象,然后對象類型變?yōu)镃ollection
        */
        Collection coll=new ArrayList();//這里發(fā)生多態(tài)了
        //使用coll對象調(diào)用add函數(shù)向集合中添加引用類型數(shù)據(jù)
        coll.add("aaaa");
        //創(chuàng)建學(xué)生對象
        Student s =new Student("張三",19);
        //將自定義類的對象添加到集合中
        coll.add(s);
        /*
        *在集合中是否可以存儲基本數(shù)據(jù)類型?
        *正常情況是不可以的,但是從jdk5之后,有了自動裝箱和拆箱的功能
        *如果使用集合添加基本數(shù)據(jù)類型,實則jvm是把基本數(shù)據(jù)類型包裝成了對應(yīng)的包裝類對象并存儲到集合中了
        */
        //Integer valueOf = Integer.valueOf(123);
        coll.add(123);//這里相當(dāng)于coll.add(Integer.valueOf(123));
        //Boolean valueOf =Boolean.valueOf(true);
        coll.add(**true**);//這里相當(dāng)于coll.add(Boolean.valueOf(true));
        //輸出集合中的數(shù)據(jù)
        System.*out*.println(coll);
    }
}

說明:
1)add函數(shù)可以把一個對象保存在集合中,但是這個函數(shù)有返回值boolean,返回的結(jié)果是告訴我們是否給集合中添加成功。添加成功則返回true。

2)能否給集合中保存基本類型數(shù)據(jù)?

嚴(yán)格意義上講是不可以的,因為集合中只能保存引用類型數(shù)據(jù),而基本類型數(shù)據(jù)不屬于引用類型數(shù)據(jù),即不屬于對象,但是在jdk5之后,基本數(shù)據(jù)類型有自動裝箱和拆箱的機制,因此我們也可以直接把基本類型的數(shù)據(jù)保存到集合中。

可是集合中存儲的根本不是基本類型的數(shù)據(jù),而是基本類型數(shù)據(jù)對應(yīng)的包裝類型的對象。

如:coll.add(100);//此代碼存在裝箱coll.add(Integer.valueOf(100));

2.2.2、刪除方法

步驟:
1)創(chuàng)建集合對象coll;
2)使用集合對象coll調(diào)用add()函數(shù)向集合中添加數(shù)據(jù);
3)輸出集合中的數(shù)據(jù);
4)使用集合對象coll調(diào)用remove()函數(shù)刪除指定的數(shù)據(jù),并使用布爾類型的數(shù)據(jù)接收刪除返回值boo;
5)輸出返回值boo和刪除后的數(shù)據(jù)coll;

image

根據(jù)指定的元素,刪除集合中對應(yīng)的元素。刪除成功則返回true,否則返回false。

package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;

/*
* Collection接口中的刪除方法remove演示
*/

public class Collection RemoveDemo {

    public static void main(String[] args) {
        //創(chuàng)建集合類對象
        Collection coll=**new** ArrayList();

        //使用集合對象coll給集合中添加數(shù)據(jù)
        coll.add("abc");
        coll.add("aaa");
        coll.add("ddd");
        coll.add("aaa");
        coll.add("yyy");

        //輸出集合中的數(shù)據(jù)
        System.*out*.println(coll);

        //使用集合對象coll調(diào)用remove刪除函數(shù)
        boolean boo = coll.remove("aaa");

//      boolean boo1 = coll.remove("aaa");
//      boolean boo = coll.remove("xxx");//由于要刪除的元素不在集合中,所以返回結(jié)果是false

        System.out.println(boo);
//      System.out.println(boo1);

        System.out.println(coll);
    }
}
image

清空集合中所有的存儲的元素。

步驟:
1)使用集合對象coll調(diào)用clear()函數(shù)清空集合中的所有元素;
2)輸出清空后的集合;

image

說明:
使用clear()函數(shù)清空集合中的元素后,集合容器依然存在,所以還可以繼續(xù)向集合中添加元素。

問題:
把集合設(shè)為null和使用集合對象中的clear()方法有什么區(qū)別?

集合=null 表示這個集合對象沒有任何引用了。如:coll=null,那么堆中對象的空間就沒有任何指向他了,而棧中的coll引用變量空間是一個空指向,所以這里會報空指針異常。

  集合.clear() 表示集合中存儲的元素全部清空,但是集合對象還存在。

2.2.3、判斷方法

image

boolean contains(Object obj)函數(shù)表示判斷集合中是否存在指定的元素。

如果有指定的元素,則返回true,沒有則返回false。

image

boolean isEmpty()判斷集合是否為空。集合中沒有存儲任何元素表示為空。

注意:
1)這個函數(shù)不是集合引用是否為null,而是判斷集合中是否有元素;
2)如果集合中有元素返回false,集合中不包含元素則返回true。
步驟:
1)創(chuàng)建集合對象coll;
2)使用集合對象coll調(diào)用add()函數(shù)向集合中添加數(shù)據(jù);
3)使用集合對象coll調(diào)用contains()函數(shù)判斷集合某個數(shù)據(jù)是否在集合中,如果有返回true,否則返回false;
4)使用集合對象coll調(diào)用clear()函數(shù)清除集合中的所有數(shù)據(jù);
5)使用集合對象coll調(diào)用isEmpty()函數(shù)判斷集合中元素是否有數(shù)據(jù),如果有數(shù)據(jù)則返回false,沒有數(shù)據(jù)則返回true;

package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
/*
*判斷方法
*/
public class Collection ContainsAndIsEmptyDemo {

    public static void main(String[] args) {

        //創(chuàng)建集合對象
        Collection coll=new ArrayList();

        //給集合添加數(shù)據(jù)
        coll.add("aaa");
        coll.add("bbb");
        coll.add("ccc");
        coll.add("ddd");

        //使用Collection接口中的contains()函數(shù)判斷某個對象是否在集合中
        //如果有,則返回true,如果沒有,則返回false
        boolean boo = coll.contains("aaa");

        System.out.println(boo);

        //輸出集合數(shù)據(jù)
        System.out.println(coll);

        //判斷集合中是否有數(shù)據(jù),如果有數(shù)據(jù)則返回false,沒有數(shù)據(jù)則返回true
        boolean boo1 = coll.isEmpty();

        System.out.println(boo1);

        //清空集合中的數(shù)據(jù)
        coll.clear();

        boolean boo2 = coll.isEmpty();

        System.out.println(boo2);
    }
}

2.2.4、Collection接口中帶All的方法

image

boolean addAll(Collectionc)表示把c集合中的元素全部添加到當(dāng)前調(diào)用這個方法的集合中。

分析和步驟:
1)使用new關(guān)鍵字創(chuàng)建集合類ArrayList的兩個對象coll和coll2,兩個對象的類型是接口Collection;
2)使用coll和coll2對象分別調(diào)用add()函數(shù)給集合添加數(shù)據(jù);
3)使用coll2對象調(diào)用addAll()函數(shù),coll集合對象作為該函數(shù)的參數(shù),最后輸出coll2的結(jié)果;

代碼實現(xiàn)如下:

package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
/*
* Collection接口中addAll方法的演示
*/

public class Collection AddAllDemo {

    public static void main(String[] args) {
        /*
        *由于Collection是接口,所以不能創(chuàng)建Collection接口的對象,
        *但是我們可以使用new關(guān)鍵字創(chuàng)建Collection接口下面的任意一個類的對象,然后對象類型變?yōu)镃ollection
        */
        Collection coll=new ArrayList();//這里發(fā)生多態(tài)了
        //再創(chuàng)建一個集合對象
        Collection coll2 = new ArrayList();

        //使用coll對象調(diào)用add函數(shù)向集合中引用類型添加數(shù)據(jù)
        coll.add("aaaa");
        coll.add("bbbb");
        coll.add("dddd");
        coll.add("eeee");

        //向集合coll2中添加數(shù)據(jù)
        coll2.add("AAAA");

        //將集合coll中的數(shù)據(jù)添加到集合coll2中
        coll2.addAll(coll);

        //輸出集合中的數(shù)據(jù)
        System.out.println(coll2);
    }
}
image

說明:判斷集合中是否包含指定集合中的所有元素。

containsAll()方法是要求作為參數(shù)傳遞的集合中的元素需要全部在調(diào)用這個方法的集合中存在,才會返回true。

分析和步驟:
1)使用new關(guān)鍵字創(chuàng)建集合類ArrayList的兩個對象coll和coll2,兩個對象的類型是接口Collection;
2)使用coll和coll2對象分別調(diào)用add()函數(shù)給集合添加數(shù)據(jù);
3)使用coll對象調(diào)用containsAll()函數(shù),coll2集合對象作為該函數(shù)的參數(shù),最后輸出布爾類型的返回結(jié)果;

package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
/*
* Collection接口中containsAll方法的演示
*/
public class Collection ContainsAllDemo {

    public static void main(String[] args) {
        /*
        *由于Collection是接口,所以不能創(chuàng)建Collection接口的對象,
        *但是我們可以使用new關(guān)鍵字創(chuàng)建Collection接口下面的任意一個類的對象,然后對象類型變?yōu)镃ollection
        */

        Collection coll=new ArrayList();//這里發(fā)生多態(tài)了
        //再創(chuàng)建一個集合對象
        Collection coll2=new ArrayList();
        //使用coll對象調(diào)用add函數(shù)向集合中引用類型添加數(shù)據(jù)
        coll.add("aaaa");
        coll.add("bbbb");
        coll.add("dddd");
        coll.add("eeee");

        //向集合coll2中添加數(shù)據(jù)
        coll2.add("AAAA");

        //將集合coll中的數(shù)據(jù)添加到集合coll2中
        coll2.addAll(coll);

        //coll集合:"aaaa" "bbbb" "dddd""eeee"
        //coll2 集合:"AAAA" "aaaa" "bbbb""dddd" "eeee"
        //判斷集合coll中是否包含集合coll2中的所有集合,如果包含返回true,否則返回false
        //boolean boo =coll.containsAll(coll2);//false 不包含

        boolean boo =coll2.containsAll(coll);//true包含

        //輸出返回值
        System.out.println(boo);
    }
}
image

說明:
1)boolean removeAll(Collection c) :表示從調(diào)用這個函數(shù)執(zhí)行的集合中刪除當(dāng)前集合與指定集合中共同的元素,刪除交集;
2)boolean retainAll(Collection c) :表示從調(diào)用這個函數(shù)執(zhí)行的集合中刪除兩個集合中不同的元素,也可以理解為保留兩個集合中共有的元素,保留交集。

分析和步驟:
1)使用new關(guān)鍵字創(chuàng)建集合類ArrayList的兩個對象coll和coll2,兩個對象的類型是接口Collection;
2)使用coll和coll2對象分別調(diào)用add()函數(shù)給集合添加數(shù)據(jù);
3)使用coll對象分別調(diào)用removeAll()和retainAll()函數(shù),coll2集合對象作為該函數(shù)的參數(shù),最后輸出布爾類型的返回結(jié)果和兩個集合對象coll和coll2;

    public static void method_3() {

        // 創(chuàng)建集合對象
        Collection coll = new ArrayList();

        Collection coll2 = new ArrayList();

        coll.add("aaaa");
        coll.add("bvvv");
        coll.add("dddd");
        coll2.add("aaaa");
        coll2.add("dddd2");

        /*
        *coll.removeAll(coll2)
        *是從coll集合中刪除 coll與coll2中相同的元素(交集)
        */

        /*
        boolean b = coll.removeAll(coll2);
        System.out.println(coll);
        System.out.println(coll2);
        System.out.println(b);
        */

        /*
        *coll.retainAll(coll2)
        *是從coll中刪除 coll與 coll2中不同的元素,也可以理解成保留2個集合的交集
        */

        boolean b = coll.retainAll(coll2);
        System.out.println(coll);
        System.out.println(coll2);
        System.out.println(b);
    }

2.2.5、toArray()遍歷集合

遍歷就是指依次從容器中獲取每一個容器中的對象元素。

問題1:我們之前直接通過輸出集合的對象名比如:System.out.println(coll);就可以輸出集合中的數(shù)據(jù)了,為什么還要遍歷集合呢?

我們之前通過輸出集合名的方式來輸出集合中的數(shù)據(jù)的方法是可以將集合中的數(shù)據(jù)輸出來,但是那些輸出的都是將集合中的對象變成字符串然后拼接在一起輸出的,這樣輸出就改變了原來對象的意思了,我們希望當(dāng)時存儲到集合中是對象,取出來的時候仍然是對象,這樣不改變原來對象元素的意思,可以使用對象操作對象本身的函數(shù)或者屬性。

問題2:現(xiàn)在會使用集合中的專用遍歷方式嗎?
不會。只會對數(shù)組進(jìn)行遍歷

在Collection集合中存在一個方法,可以把集合對象轉(zhuǎn)為數(shù)組對象:

image

案例:對集合中的學(xué)生對象,進(jìn)行遍歷(集合轉(zhuǎn)數(shù)組的方式實現(xiàn))

分析和步驟:
1)定義一個Student類,在這個類中定義兩個屬性name和age;
2)在這個類中生成toString()函數(shù),對外提供get和set方法;
3)在定義一個類,在這個類中創(chuàng)建集合對象stus;
4)使用集合對象stus調(diào)用add()函數(shù)向集合中添加學(xué)生對象;
5)使用集合對象stus調(diào)用toArray()函數(shù)將集合轉(zhuǎn)換為數(shù)組;
6)使用for循環(huán)遍歷數(shù)組,并根據(jù)數(shù)組名和下標(biāo)輸出對象即可;

package cn.xuexi.demo1;
import java.util.ArrayList;
import java.util.Collection;
import cn.xuexi.demo.Student;
/*
*遍歷集合
*/

public class Collection ToArrayDemo {

    public static void main(String[] args) {

        //創(chuàng)建集合對象
        Collection coll=new ArrayList();

        //創(chuàng)建學(xué)生對象
        Student s=new Student("張三",18);
        Student s1=new Student("李四",19);
        Student s2=new Student("王五",20);

        Student s3=new Student("鎖哥",21);

        //將學(xué)生對象添加到集合中
        coll.add(s);
        coll.add(s1);
        coll.add(s2);
        coll.add(s3);
        /*
        *想要對集合進(jìn)行遍歷我們還沒有學(xué)習(xí),但是我們學(xué)習(xí)過怎樣對數(shù)組進(jìn)行遍歷
        *所以我們可以將集合轉(zhuǎn)換為數(shù)組
        */

        /*
            int[] arr1={1,2,3};
            int x=arr1[0];
            String[] arr2={"ss","dd"};
            Strings tr=arr2[0];
        */

        Object[] arr = coll.toArray();

        //遍歷數(shù)組
        for (int i =0; i < arr.length; i++) {

            //取出數(shù)組中的對象數(shù)據(jù)
            Object obj=arr[i];
            //轉(zhuǎn)換為Student類型
            Student stu=(Student)obj;
            //打印Student類中的屬性值
//          System.out.println(stu.getName()+"======"+stu.getAge());

            /*
            *由于以上發(fā)生多態(tài),但是子類Student類中有非靜態(tài)成員函數(shù)toString(),所以根據(jù)多態(tài)的特    點,
            *對于非靜態(tài)函數(shù),如果子類有優(yōu)先使用子類中的函數(shù)
            */

            System.out.println(obj.toString());
        }
    }
}

說明:由于這里集合生成數(shù)組之后發(fā)生多態(tài)了,但是我們在Student類中復(fù)寫了Object類中的toString()函數(shù),所以根據(jù)多態(tài)的特點,對于非靜態(tài)函數(shù),如果子類有優(yōu)先使用子類中的函數(shù),直接輸出生成數(shù)組名即可。

注意:利用toArray()方法轉(zhuǎn)數(shù)組,并遍歷數(shù)組,雖然可以遍歷集合,但卻不是我們常用的方式。一般不建議使用。

3、迭代器(遍歷器)Iterator(掌握)

3.3.1、迭代器介紹

由于集合框架中的集合容器太多,而每個集合容器中保存的數(shù)據(jù)存儲的方式都不一樣。于是導(dǎo)致我們往出取數(shù)據(jù)的時候方式也完全不相同。
Java針對這些所有集合容器取出數(shù)據(jù)的方式進(jìn)行共性的抽取,于是針對所有的集合定義了一個接口,在這個接口中描述了所有集合容器的共性遍歷規(guī)則。

注意:對于集合取元素,無論是什么數(shù)據(jù)結(jié)構(gòu),最終共性的取出方式:
一個一個取,取之前先判斷,有,取一個,沒有,結(jié)束。

這種取出的共性方式:迭代。迭代可以理解為取出或者遍歷。
而這個接口它就是Iterator,它中定義了集合最基本的遍歷方式:

image
image

Iterator接口的迭代(取出、遍歷)方式:

針對一個集合,需要遍歷的時候,應(yīng)該首先去判斷集合中有沒有元素(對象),有就取出這個元素,沒有就不用再進(jìn)行遍歷了。
hasNext()函數(shù)表示判斷容器中還有沒有元素,如果有返回true,我們就可以根據(jù)這個返回的結(jié)果確定到底還要不要遍歷這個集合容器

image

next()函數(shù)表示取出當(dāng)前遍歷到的那個元素。

image

void remove()表示刪除當(dāng)前迭代器對象指向的集合中的元素。

image

對于迭代器Iterator中的函數(shù)解釋和運行原理如下圖所示:

image

說明:可以把迭代器對象理解成為一個移動的光標(biāo),開始的時候,光標(biāo)會在集合容器的最上面,然后如果使用迭代器對象調(diào)用hasNext()函數(shù)的時候,光標(biāo)會指向集合中第一個元素,如果hasNext()函數(shù)返回true,則說明有元素可以遍歷(迭代),則使用迭代器對象調(diào)用next()函數(shù)就會將當(dāng)前光標(biāo)所指向的元素取出來,如果調(diào)用remove()函數(shù),就會刪除當(dāng)前光標(biāo)所指向的元素。

每執(zhí)行完一次next()函數(shù),光標(biāo)都會往下移動,直到移動到集合的最低端,找不到元素為止。移動到最底端代表著此迭代器對象也使用完畢。

如果還想再重新迭代該集合那么需要再根據(jù)此集合重新創(chuàng)建一個迭代器對象。

注意:在使用集合對象生成迭代器對象后,那么此時這個迭代器對象已經(jīng)記錄下來此時集合中的結(jié)構(gòu),在使用迭代器遍歷的時候,一定記住不能使用集合的對象來對集合中的元素進(jìn)行刪除或者添加,如果要改動可以使用迭代器對象改動集合,如果要改動集合中的內(nèi)容可以根據(jù)改動后的集合對象再重新生成迭代器對象。

3.3.2、迭代器的使用

分析:

注意:

在我們書寫迭代器使用代碼的時候,我們首先應(yīng)該考略一個問題,如何獲得迭代器對象?
其實通過以上的分析我們不難得知,要想獲得迭代器對象必須得先創(chuàng)建一個集合的對象,然后通過集合對象調(diào)用Collection接口中的iterator()函數(shù)就可以生成迭代器對象,如下圖所示:

image

說明:由于集合種類有很多,各不相同,所以迭代器對象也會有很多,針對不同集合獲得不同的迭代器對象,但是最后使用迭代器對象調(diào)用Iterator迭代器中的函數(shù)實現(xiàn)的效果是一致的,沒有區(qū)別,即:根據(jù)迭代器對象調(diào)用hasNext()函數(shù)查看集合容器中是否含有要遍歷的元素,調(diào)用next()函數(shù)獲取集合容器中的元素。

步驟:
1)使用new關(guān)鍵字創(chuàng)建集合類ArrayList的對象coll,對象的類型是接口Collection;
2)使用對象coll調(diào)用add()函數(shù)給集合添加數(shù)據(jù);
3)以前我們都是根據(jù)集合對象名coll將集合中的數(shù)據(jù)一次性輸出,而這里我們要先使用集合對象coll調(diào)用iterator()函數(shù)獲得迭代器對象;
4)然后根據(jù)迭代器對象調(diào)用next()函數(shù)依次取出數(shù)據(jù)并輸出;
5)如果多次調(diào)用next()函數(shù)有可能會發(fā)生異常,因為集合中的數(shù)據(jù)已經(jīng)取完了,所以為了防止發(fā)生異常,我們在取數(shù)據(jù)之前使用hasNext()函數(shù)進(jìn)行判斷一下,沒有數(shù)據(jù)就不用取數(shù)據(jù)了;
6)由于是多條語句,我們可以考略使用循環(huán)while或者for;

代碼如下:

image

運行結(jié)果:

image

分析異常的原因:

image

說明:當(dāng)?shù)鲗ο笾赶蚣蠒r,可以獲取集合中的元素,如果迭代器的光標(biāo)移動集合的外邊時,此時迭代器對象不再指向集合中的任何元素,會報NoSuchElementException沒有這個元素異常。

解決方案:在使用next()函數(shù)獲取集合中元素前,使用hasNext()判斷集合中是否還有元素。

上述代碼一條語句重復(fù)執(zhí)行多次,我們可以考慮使用循環(huán)來控制執(zhí)行的次數(shù),循環(huán)條件是 迭代器對象.hasNext()為false時表示集合中沒有元素可以獲取了,循環(huán)條件迭代器對象.hasNext() 為true的時候說明還可以獲取元素。

package cn.xuexi.iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
*演示迭代器的使用
*/

public class IteratorDemo {
    public static void main(String[] args) {

        //創(chuàng)建集合對象
        Collection coll=new ArrayList();

        //向集合中添加數(shù)據(jù)
        coll.add("aaaa");
        coll.add("bbbb");
        coll.add("cccc");

        //根據(jù)當(dāng)前集合獲取迭代器對象
        Iteratorit = coll.iterator();

        //取出數(shù)據(jù)
        /*System.out.println(it.next());//it.next()表示獲取迭代器對象指向集合中的數(shù)據(jù)
        System.out.println(it.next());
        System.out.println(it.next());
        System.out.println(it.next());*/

        //使用while循環(huán)遍歷集合
        while(it.hasNext())//it.hasNext()表示循環(huán)條件,如果為true,說明集合中還有元素可以獲取,否則沒有元素
        {
            //獲取元素并輸出
            System.out.println(it.next());
        }
        /*
        *注意:針對集合每次獲取到的迭代器對象,使用完之后,迭代器中的隱式光標(biāo)就已經(jīng)到了集合的最后,這樣就無法再去使用next獲取集合中的元素。如果還要獲取,需要重新在獲取一個迭代器對象。
        */
        //報找不到元素異常,對于it迭代器對象,它已經(jīng)移動到集合中最后了,再找就沒有元素了,只能重新獲得迭代器對象
        //System.out.println(it.next());
        //使用for循環(huán)遍歷集合 推薦開發(fā)使用
        /*for (Iterator it2 = coll.iterator(); it2.hasNext();) {
            System.out.println(it2.next());
        }*/
    }
}

注意:針對集合每次獲取到的迭代器對象,使用完之后,迭代器中的隱式光標(biāo)就已經(jīng)到了集合的最后,這樣就

無法再去使用next獲取集合中的元素。如果還要獲取,需要重新在獲取一個迭代器對象。

while循環(huán)的迭代和for循環(huán)的迭代有什么不同?

while循環(huán)的迭代,由于初始化迭代器對象在while循環(huán)上面,在整個while循環(huán)結(jié)束后,迭代器對象還可以繼續(xù)使用,但是集合中已經(jīng)沒有數(shù)據(jù)了,如果還仍然使用迭代器對象繼續(xù)獲取數(shù)據(jù),會報異常,如果還要獲取,需要重新在獲取一個迭代器對象。所以對于while循環(huán)當(dāng)?shù)鲗ο笫褂猛曛?,迭代器就會變成一個沒有用的垃圾,占內(nèi)存。

對于for循環(huán)的迭代,由于初始化迭代器對象在for循環(huán)小括號中,在整個for循環(huán)結(jié)束后,迭代器對象就不能繼續(xù)使用,也不會占內(nèi)存,所以建議大家以后在開發(fā)中使用迭代器遍歷集合最好使用for循環(huán)。

總結(jié):在開發(fā)中,建議大家使用迭代器遍歷集合的時候最好使用for循環(huán)。

3.3.3、迭代器注意細(xì)節(jié)
需求:遍歷集合,遇到"abc"就把它刪除。
分析和步驟:
1)使用new關(guān)鍵字創(chuàng)建集合類ArrayList的對象coll,對象的類型是接口Collection;
2)使用集合對象coll調(diào)用add()函數(shù)給集合中添加數(shù)據(jù);
3)使用for循環(huán)遍歷集合,取出每個元素,進(jìn)行判斷,只要當(dāng)前取出的這個元素是"abc",就把它從集合中刪除;
4)在for循環(huán)的初始化值位置上使用集合對象coll獲取迭代器對象;
5)使用迭代器中的next()函數(shù)獲取數(shù)據(jù)賦值給Object類型;
6)使用判斷結(jié)構(gòu)對取出的數(shù)據(jù)和字符串”abc”進(jìn)行判斷,如果找到,則使用迭代器對象調(diào)用迭代器中的remove()函數(shù)進(jìn)行刪除,不要使用集合中的remove(obj)函數(shù),否則會報異常;

/*
*需求:遍歷集合,遇到"abc"就把它刪除。
*/
public class IteratorDemo2 {

    public static void main(String[] args) {

        Collection coll = new ArrayList();

        coll.add("abc");
        coll.add("bbbbb");
        coll.add("dddd");
        coll.add("xyz");
        coll.add("ABC");

        /*
        *遍歷集合,取出每個元素,進(jìn)行判斷,只要當(dāng)前取出的這個元素是"abc"
        *就把它從集合中刪除
        */

        for( Iterator it = coll.iterator(); it.hasNext();  ){

            //取出這個元素進(jìn)行判斷
            Object obj = it.next();
            if( obj.equals("abc") ){
                /*
                *當(dāng)我們使用迭代器對集合中的元素進(jìn)行迭代的時候,不允許使用集合自身的增刪函數(shù)
                *對集合中的元素進(jìn)行操作。  如果真的需要刪除,這時只能使用迭代器自身的remove方法
                */
                //coll.remove(obj);
                it.remove();
            }
        }
        System.out.println(coll);
    }
}

說明:如果使用集合中的remove(obj)函數(shù)進(jìn)行刪除,為什么會報異常?

由于迭代器對象是基于集合而來的,如果已經(jīng)獲取到了迭代器對象,就可以使用迭代器對象遍歷集合,而此時在遍歷集合的時候,如果使用集合對象調(diào)用集合中的函數(shù)對集合進(jìn)行增刪操作,那么對于迭代器對象而言就會導(dǎo)致最開始生成迭代器對象和修改集合之后不一樣,而在java中是不允許這樣操作的,如果想要在迭代集合的時候刪除集合中的元素可以使用迭代器Iterator中的remove()函數(shù)。

總結(jié):
1、使用迭代器對集合進(jìn)行迭代的時候,不要使用集合自身的功能(函數(shù))對集合進(jìn)行增刪操作;
2、所有的迭代器當(dāng)?shù)Y(jié)束之后,那么這個迭代器對象(隱式光標(biāo))就位于集合的最后;
3、使用迭代器迭代集合的時候,每一個hasNext()方法都對應(yīng)一個next()函數(shù),不要一個hasNext()方法對應(yīng)多個next()函數(shù)。

如下圖所示,就是一個hasNext()函數(shù)對應(yīng)多個next()函數(shù),使用是錯誤的。

image

4.可以使用增強for循環(huán)遍歷集合更加簡單一些;

但是使用增強for循環(huán)的時候需要注意集合中的數(shù)據(jù)類型是Object,因為集合中可以存儲各種引用類型數(shù)據(jù),而Object類是所有引用類型數(shù)據(jù)的父類。

代碼演示如下:

image

4、集合的細(xì)節(jié)

集合的細(xì)節(jié):

1)集合中正常情況下是不能存儲基本類型數(shù)據(jù),但是在JDK1.5后可以直接在add方法中書寫基本類型數(shù)據(jù),因為底層在操作時會對基本類型數(shù)據(jù)進(jìn)行裝箱。

image

2)集合中存儲的任何類型的元素,在存儲到集合中時,全部都會轉(zhuǎn)為Object類型;
3)從集合中取出元素時,取出的元素類型全部都是Object類型,如果想要使用類中特有的成員時,需要向下轉(zhuǎn)型;

例如上述存儲在集合中的自定義Student類,想要使用Student類中的特有的get和set函數(shù):

package cn.xuexi.iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import cn.xuexi.demo.Student;

public class IteratorDemo1 {

    public static void main(String[] args) {

        //創(chuàng)建集合類對象
        Collection coll=new ArrayList();

        //向集合中添加數(shù)據(jù)
        coll.add(new Student("張三",19));

        coll.add("aaaa");

        //遍歷取出集合中的數(shù)據(jù)
        for(Iteratorit = coll.iterator(); it.hasNext();) {
            Object obj = it.next();
            /*
            *想通過取出的對象調(diào)用Student類中特有的getName()和getAge()函數(shù)獲得屬性值
            *由于getName()和getAge()函數(shù)是Student類中的特有的函數(shù),而從集合中取出的數(shù)據(jù)
            *都是Object類型,要想使用子類Student特有的函數(shù),必須向下轉(zhuǎn)型,向下轉(zhuǎn)型有風(fēng)險
            *使用需謹(jǐn)慎,使用instanceof判斷轉(zhuǎn)型的數(shù)據(jù)類型
            */

            if(obj instanceof Student)
            {
                //說明是Student類型
                Student stu=(Student)obj;
                System.out.println(stu.getName()+"====="+stu.getAge());
            }
        }
    }
}

4)集合容器是用來保存對象的。而真正給集合中保存的不是當(dāng)前那個對象,而是對象在堆內(nèi)存中的內(nèi)存地址。
給集合中保存自定義對象:
a.使用上述自定義的Student類,在類中定義name和age屬性,生成get和set方法;
b.隨便定義一個測試類,在main函數(shù)中創(chuàng)建集合對象,同時創(chuàng)建Student類的對象;
c.將Student類的對象添加到集合中,并迭代集合,遍歷輸出結(jié)果,會發(fā)現(xiàn)打印的是Student類的對象的地址值
d.如果在Student類中復(fù)寫toString()函數(shù)就會打印name和age的屬性值;

代碼如下:

自定義學(xué)生類:

package cn.xuexi.demo;
//描述學(xué)生
public class Student {
    //屬性
    String name;
    int age;

    //定義構(gòu)造函數(shù)給屬性初始化值
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //給屬性生成get和set方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age)
{
        this.age = age;
    }

    //生成toString()函數(shù)
    public StringtoString() {
        return "Student [name=" + name +", age=" + age + "]";
    }*/
}

測試類:

package cn.xuexi.iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import cn.xuexi.demo.Student;

public class IteratorDemo2 {

    public static void main(String[] args) {

        //創(chuàng)建集合類對象
        Collection coll=new ArrayList();

        //向集合中添加數(shù)據(jù)
        coll.add(new Student("張三",19));

        //遍歷取出集合中的數(shù)據(jù)
        for(Iteratorit = coll.iterator(); it.hasNext();) {

                /*
                *如果自定義Student類中不復(fù)寫toString()函數(shù)那么就會輸出一串內(nèi)存地址
                * cn.xuexi.demo.Student@6d9dd520
                */
                System.out.println(it.next());
        }
    }
}

內(nèi)存圖解如下圖所示:

image

5、集合使用的步驟

步驟總結(jié):

  1、創(chuàng)建集合

  2、添加元素

  3、遍歷集合:

          1)獲取迭代器對象;

          2)循環(huán)迭代集合;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內(nèi)容