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

今日任務(wù)

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

1、集合框架的繼承體系

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

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

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

集合體系框架從JDK1.2才開(kāi)始存在。早期有集合,但是它們沒(méi)有形成一個(gè)體系。

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

說(shuō)明:

1)Collection是這個(gè)體系的頂級(jí)接口;

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

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

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

2、集合Collection接口

2.1、Collection接口介紹

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

image

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

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

2.2、Collection中的方法介紹

2.2.1、添加方法

image

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

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

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

步驟和分析:

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

2)使用集合對(duì)象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接口的對(duì)象,
        *但是我們可以使用new關(guān)鍵字創(chuàng)建Collection接口下面的任意一個(gè)類(lèi)的對(duì)象,然后對(duì)象類(lèi)型變?yōu)镃ollection
        */
        Collection coll=new ArrayList();//這里發(fā)生多態(tài)了
        //使用coll對(duì)象調(diào)用add函數(shù)向集合中添加引用類(lèi)型數(shù)據(jù)
        coll.add("aaaa");
        //創(chuàng)建學(xué)生對(duì)象
        Student s =new Student("張三",19);
        //將自定義類(lèi)的對(duì)象添加到集合中
        coll.add(s);
        /*
        *在集合中是否可以存儲(chǔ)基本數(shù)據(jù)類(lèi)型?
        *正常情況是不可以的,但是從jdk5之后,有了自動(dòng)裝箱和拆箱的功能
        *如果使用集合添加基本數(shù)據(jù)類(lèi)型,實(shí)則jvm是把基本數(shù)據(jù)類(lèi)型包裝成了對(duì)應(yīng)的包裝類(lèi)對(duì)象并存儲(chǔ)到集合中了
        */
        //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);
    }
}

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

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

嚴(yán)格意義上講是不可以的,因?yàn)榧现兄荒鼙4嬉妙?lèi)型數(shù)據(jù),而基本類(lèi)型數(shù)據(jù)不屬于引用類(lèi)型數(shù)據(jù),即不屬于對(duì)象,但是在jdk5之后,基本數(shù)據(jù)類(lèi)型有自動(dòng)裝箱和拆箱的機(jī)制,因此我們也可以直接把基本類(lèi)型的數(shù)據(jù)保存到集合中。

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

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

2.2.2、刪除方法

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

image

根據(jù)指定的元素,刪除集合中對(duì)應(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)建集合類(lèi)對(duì)象
        Collection coll=**new** ArrayList();

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

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

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

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

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

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

清空集合中所有的存儲(chǔ)的元素。

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

image

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

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

集合=null 表示這個(gè)集合對(duì)象沒(méi)有任何引用了。如:coll=null,那么堆中對(duì)象的空間就沒(méi)有任何指向他了,而棧中的coll引用變量空間是一個(gè)空指向,所以這里會(huì)報(bào)空指針異常。

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

2.2.3、判斷方法

image

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

如果有指定的元素,則返回true,沒(méi)有則返回false。

image

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

注意:
1)這個(gè)函數(shù)不是集合引用是否為null,而是判斷集合中是否有元素;
2)如果集合中有元素返回false,集合中不包含元素則返回true。
步驟:
1)創(chuàng)建集合對(duì)象coll;
2)使用集合對(duì)象coll調(diào)用add()函數(shù)向集合中添加數(shù)據(jù);
3)使用集合對(duì)象coll調(diào)用contains()函數(shù)判斷集合某個(gè)數(shù)據(jù)是否在集合中,如果有返回true,否則返回false;
4)使用集合對(duì)象coll調(diào)用clear()函數(shù)清除集合中的所有數(shù)據(jù);
5)使用集合對(duì)象coll調(diào)用isEmpty()函數(shù)判斷集合中元素是否有數(shù)據(jù),如果有數(shù)據(jù)則返回false,沒(méi)有數(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)建集合對(duì)象
        Collection coll=new ArrayList();

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

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

        System.out.println(boo);

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

        //判斷集合中是否有數(shù)據(jù),如果有數(shù)據(jù)則返回false,沒(méi)有數(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)用這個(gè)方法的集合中。

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

代碼實(shí)現(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接口的對(duì)象,
        *但是我們可以使用new關(guān)鍵字創(chuàng)建Collection接口下面的任意一個(gè)類(lèi)的對(duì)象,然后對(duì)象類(lèi)型變?yōu)镃ollection
        */
        Collection coll=new ArrayList();//這里發(fā)生多態(tài)了
        //再創(chuàng)建一個(gè)集合對(duì)象
        Collection coll2 = new ArrayList();

        //使用coll對(duì)象調(diào)用add函數(shù)向集合中引用類(lèi)型添加數(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

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

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

分析和步驟:
1)使用new關(guān)鍵字創(chuàng)建集合類(lèi)ArrayList的兩個(gè)對(duì)象coll和coll2,兩個(gè)對(duì)象的類(lèi)型是接口Collection;
2)使用coll和coll2對(duì)象分別調(diào)用add()函數(shù)給集合添加數(shù)據(jù);
3)使用coll對(duì)象調(diào)用containsAll()函數(shù),coll2集合對(duì)象作為該函數(shù)的參數(shù),最后輸出布爾類(lèi)型的返回結(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接口的對(duì)象,
        *但是我們可以使用new關(guān)鍵字創(chuàng)建Collection接口下面的任意一個(gè)類(lèi)的對(duì)象,然后對(duì)象類(lèi)型變?yōu)镃ollection
        */

        Collection coll=new ArrayList();//這里發(fā)生多態(tài)了
        //再創(chuàng)建一個(gè)集合對(duì)象
        Collection coll2=new ArrayList();
        //使用coll對(duì)象調(diào)用add函數(shù)向集合中引用類(lèi)型添加數(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

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

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

    public static void method_3() {

        // 創(chuàng)建集合對(duì)象
        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個(gè)集合的交集
        */

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

2.2.5、toArray()遍歷集合

遍歷就是指依次從容器中獲取每一個(gè)容器中的對(duì)象元素。

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

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

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

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

image

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

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

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)建集合對(duì)象
        Collection coll=new ArrayList();

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

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

        //將學(xué)生對(duì)象添加到集合中
        coll.add(s);
        coll.add(s1);
        coll.add(s2);
        coll.add(s3);
        /*
        *想要對(duì)集合進(jìn)行遍歷我們還沒(méi)有學(xué)習(xí),但是我們學(xué)習(xí)過(guò)怎樣對(duì)數(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ù)組中的對(duì)象數(shù)據(jù)
            Object obj=arr[i];
            //轉(zhuǎn)換為Student類(lèi)型
            Student stu=(Student)obj;
            //打印Student類(lèi)中的屬性值
//          System.out.println(stu.getName()+"======"+stu.getAge());

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

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

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

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

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

3.3.1、迭代器介紹

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

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

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

image
image

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

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

image

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

image

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

image

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

image

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

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

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

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

3.3.2、迭代器的使用

分析:

注意:

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

image

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

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

代碼如下:

image

運(yùn)行結(jié)果:

image

分析異常的原因:

image

說(shuō)明:當(dāng)?shù)鲗?duì)象指向集合時(shí),可以獲取集合中的元素,如果迭代器的光標(biāo)移動(dòng)集合的外邊時(shí),此時(shí)迭代器對(duì)象不再指向集合中的任何元素,會(huì)報(bào)NoSuchElementException沒(méi)有這個(gè)元素異常。

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

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

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)建集合對(duì)象
        Collection coll=new ArrayList();

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

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

        //取出數(shù)據(jù)
        /*System.out.println(it.next());//it.next()表示獲取迭代器對(duì)象指向集合中的數(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,說(shuō)明集合中還有元素可以獲取,否則沒(méi)有元素
        {
            //獲取元素并輸出
            System.out.println(it.next());
        }
        /*
        *注意:針對(duì)集合每次獲取到的迭代器對(duì)象,使用完之后,迭代器中的隱式光標(biāo)就已經(jīng)到了集合的最后,這樣就無(wú)法再去使用next獲取集合中的元素。如果還要獲取,需要重新在獲取一個(gè)迭代器對(duì)象。
        */
        //報(bào)找不到元素異常,對(duì)于it迭代器對(duì)象,它已經(jīng)移動(dòng)到集合中最后了,再找就沒(méi)有元素了,只能重新獲得迭代器對(duì)象
        //System.out.println(it.next());
        //使用for循環(huán)遍歷集合 推薦開(kāi)發(fā)使用
        /*for (Iterator it2 = coll.iterator(); it2.hasNext();) {
            System.out.println(it2.next());
        }*/
    }
}

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

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

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

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

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

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

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

/*
*需求:遍歷集合,遇到"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");

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

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

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

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

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

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

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

image

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

但是使用增強(qiáng)for循環(huán)的時(shí)候需要注意集合中的數(shù)據(jù)類(lèi)型是Object,因?yàn)榧现锌梢源鎯?chǔ)各種引用類(lèi)型數(shù)據(jù),而Object類(lèi)是所有引用類(lèi)型數(shù)據(jù)的父類(lèi)。

代碼演示如下:

image

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

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

1)集合中正常情況下是不能存儲(chǔ)基本類(lèi)型數(shù)據(jù),但是在JDK1.5后可以直接在add方法中書(shū)寫(xiě)基本類(lèi)型數(shù)據(jù),因?yàn)榈讓釉诓僮鲿r(shí)會(huì)對(duì)基本類(lèi)型數(shù)據(jù)進(jìn)行裝箱。

image

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

例如上述存儲(chǔ)在集合中的自定義Student類(lèi),想要使用Student類(lèi)中的特有的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)建集合類(lèi)對(duì)象
        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();
            /*
            *想通過(guò)取出的對(duì)象調(diào)用Student類(lèi)中特有的getName()和getAge()函數(shù)獲得屬性值
            *由于getName()和getAge()函數(shù)是Student類(lèi)中的特有的函數(shù),而從集合中取出的數(shù)據(jù)
            *都是Object類(lèi)型,要想使用子類(lèi)Student特有的函數(shù),必須向下轉(zhuǎn)型,向下轉(zhuǎn)型有風(fēng)險(xiǎn)
            *使用需謹(jǐn)慎,使用instanceof判斷轉(zhuǎn)型的數(shù)據(jù)類(lèi)型
            */

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

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

代碼如下:

自定義學(xué)生類(lèi):

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 + "]";
    }*/
}

測(cè)試類(lèi):

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)建集合類(lèi)對(duì)象
        Collection coll=new ArrayList();

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

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

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

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

image

5、集合使用的步驟

步驟總結(jié):

  1、創(chuàng)建集合

  2、添加元素

  3、遍歷集合:

          1)獲取迭代器對(duì)象;

          2)循環(huán)迭代集合;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容