6.3 集合框架
6.3.1簡述
1、由來
對象用於封裝特有數據,對象多了需要存儲,且對象的個數不確定,於是 SUN公司專門設計了一組類,這組類因內部的數據結構不同,不斷向上抽取,就形成了各種不同的具體容器,即容器類,這些容器共同組成了集合框架(Collection Framework)。集合框架包含在java.util 包中。
任何集合框架都包含三大塊內容:對外的接口、接口的實現和對集合運算的算法。
2、 從體系上講,集合框架可分爲兩種:
①:Collection 接口:
·Set:集,無序性,無重複
·List:列表,以線性方式存儲,只能在頭或尾添加,或者在指定的位置後面插入新對象
②:Map 接口。
整個框架如下圖:
3、特點
·集合用於存儲對象。
·集合的長度是可變的
·集合中不可以存儲基本數據類型
4、集合與數組的區別
·數組的長度是固定的;集合長度是可變的。
·數組可以存儲基本數據類型,也可以存儲引用數據類型;集合只能存儲引用數據類型。
·數組存儲的元素必須是同一個數據類型;集合存儲的對象可以是不同數據類型
6.3.2 Collection
java.util.collection接口是描述Set和List集合類型的根接口。
1、集合操作的常見方法,包括:
以代碼的形式介紹:
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public void CollectionDemo{ public static void main(String[] args){ Collection c1 = new ArrayList(); Collection c2 = new ArrayList(); show(); } public static void show(Collection coll){ //1、添加元素(add) c1.add("hufei1"); c1.add("hufei2"); System.out.println(c1);//測試代碼 c2.add("hufei3"); c2.add("hufei4"); c2.add("hufei1"); c1.addAll(c2);//將c2中的元素添加到c1中 System.out.println(c1);//測試代碼 //2、刪除元素 c1.remove("hufei1");//刪除hufei1元素,同時改變了集合的長度 System.out.println(c1);//測試代碼 c1.clear();//清空集合 System.out.println(c1);//測試代碼 c1.removeAll(c2);//將倆個集合中的相同的元素從調用該的集合刪除 System.out.println(c1);//測試代碼 //3、判斷元素 System.out.println(c1.contain("hufei2"));//測試代碼 System.out.println(c1.containAll(c2));//測試代碼 System.out.println(c1.retainAll(c2));//取交集,保留倆集合相同的元 //素,除此之外還有isEmpty(),containAll(collection c), //4、獲取元素(Iterator) //下面的代碼會詳述 }
2、關於迭代器
定義:按次序一個一個的獲取集合中的所有對象
使用迭代器的基本機制:
集合—>迭代器—>hasNext()測試—真—>連續調用next()方法—>對象
—假—>不再有對象有效
迭代器原理:在集合框架中,容器種類很多,每種容器的數據結構都有自己的特點,而要取出其中的元素,就必須依賴於具體容器來實現迭代器,從而創造自己獨有的迭代器,這個迭代器必須做倆件事,判斷有沒有元素和取出元素,即hasNext()和next(),把這些容器的獨有迭代器向外抽取就形成了Iterator接口。他是對所有的Collection容器進行元素取出的公共接口
接上的代碼:
//與forEach相結合 Iterator it = c1.Iterator(); for(it.hasNext()){ //以上代碼也可寫成for(Iterator it = c1.Iterator();it.hasNext()) System.out.println(it.next()); } //與while相結合 Iterator it = c1.Iterator(); while(it.hasNext()){ System.out.println(it.next()); //它與for循環的區別在於在代碼結束後,引用還留在內存中,所以是否用它視 //情況而定 }
6.3.3 List
1、常見方法
1)、常見方法的共同特點:可以操作角標
2)、以代碼的形式介紹方法:
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; public class ListIterator { public static void main(String[] args){ List list = new ArrayList(); show(list); } public static void show(List list){ //1、添加元素(add) list.add("hufei1"); list.add("hufei2"); list.add("hufei3"); System.out.println(list); //2、刪除元素 System.out.println(list.remove(0));//刪除角標爲2的元素,同時 //改變了集合的長度 //3、修改元素 System.out.println(list.set(1, "hufei4"));// //4、獲取元素 System.out.println(list.get(0));//測試代碼 //5、獲取子元素 System.out.println(list.subList(1, 2));//返回指定的 角標1(包 //括 )和 角標2(不包括)之間的子元素 } }
2、ListIterator接口
1)、list獲取元素的方法
接上面的代碼:
/獲取元素的方法一 Iterator it = list.Iterator(); for(it.hasNext()){ System.out.println(it.next()); } //獲取元素的方法二 for(int x = 0; x < List.size()); x++){ System.out.println(list.get(x));//list獨有的方法 }
2)、由來(利用代碼解釋)
importjava.util.Iterator; importjava.util.List; classListIteratorDemo{ publicstaticvoidmain(String[] args){ list.add("hufei1"); list.add("hufei2"); list.add("hufei3"); Iterator it = list.Iterator(); while(it.hasNext()){ Object obj = it.next();//用Object的原因是在add方法添加時,就加的是 //Object對象, if(obj.equals("hufei2")) list.add("hufei4"); //這樣做會發生ConcurrentModificationException異常,因爲list與 //Iterator同時發生, else System.out.println(obj); } System.out.println(list); } }
由於在迭代器過程中,使用集合操作元素,容易出現異常,所以可以使用Iterator接口的子類接口ListIterator來完成在迭代中對元素進行更多的操作。
以上迭代器的代碼可改爲以下代碼:
java.util.ListIterator it = list.listIterator(); while(it.hasNext()){ Object obj = it.next(); if(obj.equals("hufei2")) it.add("hufei5"); System.out.println(obj);
3、ListIterator的常見方法
ListIterator可以在迭代過程中實現增刪改查,而且只有List集合具備該迭代功能
hasNext();以正向遍歷列表時,如果列表迭代器有多個元素,則返回 true
hasPrevious();如果以逆向遍歷列表,列表迭代器有多個元素,則返回 true。
nextIndex() 返回對 next 的後續調用所返回元素的索引。
4、List常用子類
lVector:內部是數組數據結構,是同步的
Vector只保存對象的引用,而不是實際對象
lArrayList:內部是數組數據結構,是不同步的,替代了Vector,由於空間連續,所以查詢的速度快
import java.util.ArrayList; import java.util.Iterator; public class ArrayListTest { /** * ArrayList集合存儲自定義對象的 */ public static void main(String[] args) { ArrayList al = new ArrayList();//初始容量爲 10 的空列表 al.add(new Person("zhangsan1",21)); al.add(new Person("zhangsan2",22)); al.add(new Person("zhangsan3",23)); al.add(new Person("zhangsan4",24)); al.add(5);//自動裝箱,基本數據類型賦值給引用數據類型al.add(5) //相當於al.add(new Integer(5)) Iterator it = al.iterator(); while(it.hasNext()){ //System.out.println(it.next().getName); //失敗的原因,在add的時候,已經自動將Person提升爲Object類 //型了,但Object中沒有getName方法 //System.out.println(((Person)it.next()).getName()+"::" //+((Person)it.next()).getAge());//在裏面放倆個next,它會指向下一個數據,會輸出zhangsan1::22 zhangsan 3 : :24,會出現問題,所以代碼應該如下: Person p = (Person) it.next(); //多次調用it.next()先給它取個名字 System.out.println(p.getName()+"::"+p.getAge()); } } }
將以下代碼放置於另一個java文件中
public class Person{ private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); // TODO Auto-generated constructor stub } 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; } }
lLinkedList:內部是鏈表數據結構,是不同步的。增刪元素速度快
面試題:
import java.util.Iterator; import java.util.LinkedList; class Queue{ private LinkedList link; Queue(){ link = new LinkedList(); } public void myAdd(Object obj){ link.add(obj); } public Object myGet(){ return link.removeLast();// 隊列:先進先出(FIFO) //return link.removeFirst();//堆棧:先進後出(FILO) } public boolean isNull(){ return link.isEmpty(); } } public class InterviewTest { /* * 請使用LinkedList來模擬一個堆棧或者隊列數據結構容器, * 即描述這樣一個容器,給使用對象提供一個容器完成這倆種結構的一種 * 堆棧:先進後出(FILO) * 隊列:先進先出(FIFO) */ public static void main(String[] args) { Queue q = new Queue(); q.myAdd("hufei1"); q.myAdd("hufei2"); q.myAdd("hufei3"); while(!q.isNull()){ System.out.println(q.myGet()); } } }