今日任務(wù)
1校坑、集合框架繼承體系(理解)
2晾虑、Collection接口介紹(掌握常用Collection方法)
3、迭代器(掌握)
4仙粱、集合的細節(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包下省咨。
Collection接口是集合的頂層接口肃弟,它下面有子接口或者間接的實現(xiàn)類,而具體的實現(xiàn)類中有些可以保存重復(fù)元素茸炒,有些不能保存重復(fù)元素愕乎,有些可以保證數(shù)據(jù)有序阵苇,一些則無序壁公。
說明:在學(xué)習(xí)集合框架的時候感论,遇到的所有E類型,全部理解成Object類型紊册。
2.2比肄、Collection中的方法介紹
2.2.1、添加方法
說明:把指定的引用類型數(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;
根據(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);
}
}
清空集合中所有的存儲的元素。
步驟:
1)使用集合對象coll調(diào)用clear()函數(shù)清空集合中的所有元素裙椭;
2)輸出清空后的集合躏哩;
說明:
使用clear()函數(shù)清空集合中的元素后,集合容器依然存在骇陈,所以還可以繼續(xù)向集合中添加元素震庭。
問題:
把集合設(shè)為null和使用集合對象中的clear()方法有什么區(qū)別?
集合=null 表示這個集合對象沒有任何引用了你雌。如:coll=null,那么堆中對象的空間就沒有任何指向他了器联,而棧中的coll引用變量空間是一個空指向,所以這里會報空指針異常婿崭。
集合.clear() 表示集合中存儲的元素全部清空拨拓,但是集合對象還存在。
2.2.3氓栈、判斷方法
boolean contains(Object obj)函數(shù)表示判斷集合中是否存在指定的元素渣磷。
如果有指定的元素,則返回true授瘦,沒有則返回false醋界。
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的方法
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);
}
}
說明:判斷集合中是否包含指定集合中的所有元素鹃操。
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);
}
}
說明:
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ù)組進行遍歷
在Collection集合中存在一個方法什湘,可以把集合對象轉(zhuǎn)為數(shù)組對象:
案例:對集合中的學(xué)生對象,進行遍歷(集合轉(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);
/*
*想要對集合進行遍歷我們還沒有學(xué)習(xí)绎巨,但是我們學(xué)習(xí)過怎樣對數(shù)組進行遍歷
*所以我們可以將集合轉(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ù)的方式進行共性的抽取罩息,于是針對所有的集合定義了一個接口,在這個接口中描述了所有集合容器的共性遍歷規(guī)則个扰。
注意:對于集合取元素瓷炮,無論是什么數(shù)據(jù)結(jié)構(gòu),最終共性的取出方式:
一個一個取递宅,取之前先判斷娘香,有,取一個办龄,沒有烘绽,結(jié)束。
這種取出的共性方式:迭代俐填。迭代可以理解為取出或者遍歷安接。
而這個接口它就是Iterator,它中定義了集合最基本的遍歷方式:
Iterator接口的迭代(取出英融、遍歷)方式:
針對一個集合盏檐,需要遍歷的時候,應(yīng)該首先去判斷集合中有沒有元素(對象)驶悟,有就取出這個元素胡野,沒有就不用再進行遍歷了。
hasNext()函數(shù)表示判斷容器中還有沒有元素痕鳍,如果有返回true硫豆,我們就可以根據(jù)這個返回的結(jié)果確定到底還要不要遍歷這個集合容器
next()函數(shù)表示取出當(dāng)前遍歷到的那個元素。
void remove()表示刪除當(dāng)前迭代器對象指向的集合中的元素。
對于迭代器Iterator中的函數(shù)解釋和運行原理如下圖所示:
說明:可以把迭代器對象理解成為一個移動的光標(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)饮亏,在使用迭代器遍歷的時候,一定記住不能使用集合的對象來對集合中的元素進行刪除或者添加,如果要改動可以使用迭代器對象改動集合挠铲,如果要改動集合中的內(nèi)容可以根據(jù)改動后的集合對象再重新生成迭代器對象甘邀。
3.3.2伟骨、迭代器的使用
分析:
注意:
在我們書寫迭代器使用代碼的時候仔夺,我們首先應(yīng)該考略一個問題,如何獲得迭代器對象南捂?
其實通過以上的分析我們不難得知吴裤,要想獲得迭代器對象必須得先創(chuàng)建一個集合的對象,然后通過集合對象調(diào)用Collection接口中的iterator()函數(shù)就可以生成迭代器對象溺健,如下圖所示:
說明:由于集合種類有很多麦牺,各不相同,所以迭代器對象也會有很多矿瘦,針對不同集合獲得不同的迭代器對象枕面,但是最后使用迭代器對象調(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ù)進行判斷一下,沒有數(shù)據(jù)就不用取數(shù)據(jù)了瞭吃;
6)由于是多條語句碌嘀,我們可以考略使用循環(huán)while或者for;
代碼如下:
運行結(jié)果:
分析異常的原因:
說明:當(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扇谣、迭代器注意細節(jié)
需求:遍歷集合昧捷,遇到"abc"就把它刪除。
分析和步驟:
1)使用new關(guān)鍵字創(chuàng)建集合類ArrayList的對象coll罐寨,對象的類型是接口Collection靡挥;
2)使用集合對象coll調(diào)用add()函數(shù)給集合中添加數(shù)據(jù);
3)使用for循環(huán)遍歷集合鸯绿,取出每個元素跋破,進行判斷,只要當(dāng)前取出的這個元素是"abc"瓶蝴,就把它從集合中刪除毒返;
4)在for循環(huán)的初始化值位置上使用集合對象coll獲取迭代器對象;
5)使用迭代器中的next()函數(shù)獲取數(shù)據(jù)賦值給Object類型舷手;
6)使用判斷結(jié)構(gòu)對取出的數(shù)據(jù)和字符串”abc”進行判斷拧簸,如果找到,則使用迭代器對象調(diào)用迭代器中的remove()函數(shù)進行刪除聚霜,不要使用集合中的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");
/*
*遍歷集合祷安,取出每個元素,進行判斷兔乞,只要當(dāng)前取出的這個元素是"abc"
*就把它從集合中刪除
*/
for( Iterator it = coll.iterator(); it.hasNext(); ){
//取出這個元素進行判斷
Object obj = it.next();
if( obj.equals("abc") ){
/*
*當(dāng)我們使用迭代器對集合中的元素進行迭代的時候汇鞭,不允許使用集合自身的增刪函數(shù)
*對集合中的元素進行操作。 如果真的需要刪除庸追,這時只能使用迭代器自身的remove方法
*/
//coll.remove(obj);
it.remove();
}
}
System.out.println(coll);
}
}
說明:如果使用集合中的remove(obj)函數(shù)進行刪除霍骄,為什么會報異常?
由于迭代器對象是基于集合而來的淡溯,如果已經(jīng)獲取到了迭代器對象读整,就可以使用迭代器對象遍歷集合,而此時在遍歷集合的時候咱娶,如果使用集合對象調(diào)用集合中的函數(shù)對集合進行增刪操作米间,那么對于迭代器對象而言就會導(dǎo)致最開始生成迭代器對象和修改集合之后不一樣,而在java中是不允許這樣操作的膘侮,如果想要在迭代集合的時候刪除集合中的元素可以使用迭代器Iterator中的remove()函數(shù)屈糊。
總結(jié):
1、使用迭代器對集合進行迭代的時候琼了,不要使用集合自身的功能(函數(shù))對集合進行增刪操作逻锐;
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ù),使用是錯誤的锄俄。
4.可以使用增強for循環(huán)遍歷集合更加簡單一些局劲;
但是使用增強for循環(huán)的時候需要注意集合中的數(shù)據(jù)類型是Object,因為集合中可以存儲各種引用類型數(shù)據(jù)奶赠,而Object類是所有引用類型數(shù)據(jù)的父類鱼填。
代碼演示如下:
4、集合的細節(jié)
集合的細節(jié):
1)集合中正常情況下是不能存儲基本類型數(shù)據(jù)毅戈,但是在JDK1.5后可以直接在add方法中書寫基本類型數(shù)據(jù)苹丸,因為底層在操作時會對基本類型數(shù)據(jù)進行裝箱愤惰。
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)存圖解如下圖所示:
5鲜侥、集合使用的步驟
步驟總結(jié):
1褂始、創(chuàng)建集合
2、添加元素
3描函、遍歷集合:
1)獲取迭代器對象崎苗;
2)循環(huán)迭代集合;