一、集合&迭代器
- 集合體系結(jié)構(gòu)
集合體系圖
集合體系圖.png
在最頂層的父接口Collection中一定定義了所有子類集合的共同屬性和方法,因此我們首先需要學(xué)習(xí)Collection中共性方法,然后再去針對(duì)每個(gè)子類集合學(xué)習(xí)它的特有方法
- 案例代碼一:
package com.neuedu.demo; import java.util.ArrayList; /* * ArrayList * 集合的體系結(jié)構(gòu): * 由于不同的數(shù)據(jù)結(jié)構(gòu)(數(shù)據(jù)的組織,存儲(chǔ)方式),所以Java為我們提供了不同的集合, * 但是不同的集合他們的功能都是相似,不斷的向上提取,將共性抽取出來,這就是集合體系結(jié)構(gòu)形成的原因 * * 體系結(jié)構(gòu): * 怎么學(xué)習(xí)?最頂層開始學(xué)習(xí),因?yàn)樽铐攲影怂械墓残?* 怎么使用?使用最底層,因?yàn)樽畹讓泳褪蔷唧w的實(shí)現(xiàn) * * Collection * List * ArrayList */ public class CollectionDemo { public static void main(String[] args) { //創(chuàng)建集合對(duì)象 ArrayList al = new ArrayList(); //添加元素 al.add("hello"); al.add("world"); al.add("java"); //遍歷集合 for(int x = 0;x < al.size();x++) { System.out.println(al.get(x)); } } }
- Collection中的常用功能
boolean add(Object e): 向集合中添加元素
void clear():清空集合中所有元素
boolean contains(Object o):判斷集合中是否包含某個(gè)元素
boolean isEmpty():判斷集合中的元素是否為空
boolean remove(Object o):根據(jù)元素的內(nèi)容來刪除某個(gè)元素
int size():獲取集合的長度
Object[] toArray():能夠?qū)⒓限D(zhuǎn)換成數(shù)組并把集合中的元素存儲(chǔ)到數(shù)組中
- 案例代碼二:
package com.neuedu.demo import java.util.ArrayList; import java.util.Collection; /* * Collection * boolean add(E e) * void clear() * boolean contains(Object o) * boolean isEmpty() * boolean remove(Object o) * int size() * Object[] toArray() * Iterator<E> iterator() * */ public class CollectionDemo2 { public static void main(String[] args) { //創(chuàng)建集合對(duì)象 //Collection c = new Collection();//Collection是接口,不能實(shí)例化 Collection c = new ArrayList();//多態(tài),父類引用指向子類對(duì)象 //boolean add(E e) System.out.println(c.add("hello"));//永遠(yuǎn)可以添加成功,因?yàn)锳rrayList他允許重復(fù) System.out.println(c.add("world")); //void clear():清空集合 //c.clear(); //boolean contains(Object o) :判斷集合中是否包含指定元素 //System.out.println(c.contains("java")); //boolean isEmpty() :是否為空 //System.out.println(c.isEmpty()); //boolean remove(Object o) :刪除元素 //System.out.println(c.remove("java")); //int size() :返回集合中的元素個(gè)數(shù) //System.out.println(c.size()); //Object[] toArray() :將集合轉(zhuǎn)換成一個(gè)Object類型的數(shù)組 Object[] objs = c.toArray(); for (int i = 0; i < objs.length; i++) { System.out.println(objs[i]); } System.out.println(c); } }
- 迭代器
- java中提供了很多個(gè)集合,它們?cè)诖鎯?chǔ)元素時(shí),采用的存儲(chǔ)方式不同。我們要取出這些集合中的元素,可通過一種通用的獲取方式來完成。
Collection集合元素的通用獲取方式:在取元素之前先要判斷集合中有沒有元素,如果有,就把這個(gè)元素取出來,繼續(xù)在判斷,如果還有就再取出出來。一直把集合中的所有元素全部取出。這種取出方式專業(yè)術(shù)語稱為迭代。- 集合中把這種取元素的方式描述在Iterator接口中。Iterator接口的常用方法如下
hasNext()方法:判斷集合中是否有元素可以迭代
next()方法:用來返回迭代的下一個(gè)元素,并把指針向后移動(dòng)一位。
- 案例代碼三:
package com.neuedu.demo; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /* * 集合的遍歷方式: * 1.toArray(),可以把集合轉(zhuǎn)換成數(shù)組,然后遍歷數(shù)組即可 * 2.iterator(),可以返回一個(gè)迭代器對(duì)象,我們可以通過迭代器對(duì)象來迭代集合 * * Iterator:可以用于遍歷集合 * E next() :返回下一個(gè)元素 * boolean hasNext() :判斷是否有元素可以獲取 * * 注意:Exception in thread "main" java.util.NoSuchElementException * 使用next方法獲取下一個(gè)元素,如果沒有元素可以獲取,則出現(xiàn)NoSuchElementException */ public class IteratorDemo { public static void main(String[] args) { //method(); //創(chuàng)建集合對(duì)象 Collection c = new ArrayList(); //添加元素 c.add("hello"); c.add("world"); c.add("java"); //獲取迭代器對(duì)象 Iterator it = c.iterator(); //Object next() :返回下一個(gè)元素 //boolean hasNext() :判斷是否有元素可以獲取 /*if(it.hasNext()) System.out.println(it.next()); if(it.hasNext()) System.out.println(it.next()); if(it.hasNext()) System.out.println(it.next()); if(it.hasNext()) System.out.println(it.next());*/ while(it.hasNext()) { System.out.println(it.next()); } } private static void method() { //創(chuàng)建集合對(duì)象 Collection c = new ArrayList(); //添加元素 c.add("hello"); c.add("world"); c.add("java"); //獲取數(shù)組 Object[] objs = c.toArray(); //遍歷數(shù)組 for (int i = 0; i < objs.length; i++) { System.out.println(objs[i]); } } }
- 并發(fā)修改異常:
- 并發(fā)修改異常產(chǎn)生原因:
當(dāng)使用迭代器遍歷集合的時(shí)候,使用了集合中的 增加/刪除 方法,導(dǎo)致并發(fā)修改異常產(chǎn)
- 案例代碼四:
package com.neuedu.demo; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /* * 需求:判斷集合中是否包含元素java,如果有則添加元素android * Exception in thread "main" java.util.ConcurrentModificationException:并發(fā)修改異常 * 迭代器是依賴于集合的,相當(dāng)于集合的一個(gè)副本,當(dāng)?shù)髟诓僮鞯臅r(shí)候,如果發(fā)現(xiàn)和集合不一樣,則拋出異常 * * 解決方案: * 你就別使用迭代器 * 在使用迭代器進(jìn)行遍歷的時(shí)候使用迭代器來進(jìn)行修改 */ public class IteratorDemo3 { public static void main(String[] args) { //method(); //創(chuàng)建集合對(duì)象 //Collection c = new ArrayList(); List c = new ArrayList(); //添加元素 c.add("hello"); c.add("world"); c.add("java"); //我們可以通過遍歷來獲取集合中的每一個(gè)元素,然后進(jìn)行比較即可 /*Iterator it = c.iterator(); while(it.hasNext()) { String s = (String)it.next(); if(s.equals("java")) { c.add("android"); } }*/ ListIterator lit = c.listIterator(); while(lit.hasNext()) { String s = (String)lit.next(); if(s.equals("java")) { lit.add("android"); } } System.out.println(c); } private static void method() { //創(chuàng)建集合對(duì)象 Collection c = new ArrayList(); //添加元素 c.add("hello"); c.add("world"); c.add("java"); //判斷集合中是否包含元素java if(c.contains("java")) { c.add("android"); } System.out.println(c); } }
二、增強(qiáng)for&泛型
- 泛型
- 泛型的引入
在前面學(xué)習(xí)集合時(shí),我們都知道集合中是可以存放任意對(duì)象的,只要把對(duì)象存儲(chǔ)集合后,那么這時(shí)他們都會(huì)被提升成Object類型。當(dāng)我們?cè)谌〕雒恳粋€(gè)對(duì)象,并且進(jìn)行相應(yīng)的操作,這時(shí)必須采用類型轉(zhuǎn)換
- 案例代碼五:
package com.neuedu.demo; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /* * 使用集合存儲(chǔ)自定義對(duì)象并遍歷 * 由于集合可以存儲(chǔ)任意類型的對(duì)象,當(dāng)我們存儲(chǔ)了不同類型的對(duì)象,就有可能在轉(zhuǎn)換的時(shí)候出現(xiàn)類型轉(zhuǎn)換異常, * 所以java為了解決這個(gè)問題,給我們提供了一種機(jī)制,叫做泛型 * */ public class GenericDemo { public static void main(String[] args) { //創(chuàng)建集合對(duì)象 Collection c = new ArrayList(); //創(chuàng)建元素對(duì)象 Student s = new Student("zhangsan",18); Student s2 = new Student("lisi",19); //添加元素對(duì)象 c.add(s); c.add(s2); //遍歷集合對(duì)象 Iterator it = c.iterator(); while(it.hasNext()) { String str = (String)it.next(); System.out.println(str); } } } class Student { String name; int age; public Student(String name,int age) { this.name = name; this.age = age; } }以上代碼會(huì)發(fā)生強(qiáng)制轉(zhuǎn)換異常,原因就是String str = (String)it.next() ,存入集合的是Student,而強(qiáng)轉(zhuǎn)為String,String與Student之間沒有任何子父關(guān)系不能強(qiáng)轉(zhuǎn),未使用泛型前有可能發(fā)聲強(qiáng)制轉(zhuǎn)換異常的問題
- 泛型的使用
當(dāng)類上定義<>的時(shí)候就可以使用泛型,例如ArrayList類的定義:
class ArrayList<E>,那么我們?cè)趧?chuàng)建ArrayList對(duì)象的時(shí)候就可以指定<>中E的類型
ArrayList<String> al=new ArrayList<String>(),那么String就把E替換掉了
- 案例代碼六:
package com.neuedu.demo; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /* * 使用集合存儲(chǔ)自定義對(duì)象并遍歷 * 由于集合可以存儲(chǔ)任意類型的對(duì)象,當(dāng)我們存儲(chǔ)了不同類型的對(duì)象,就有可能在轉(zhuǎn)換的時(shí)候出現(xiàn)類型轉(zhuǎn)換異常, * 所以java為了解決這個(gè)問題,給我們提供了一種機(jī)制,叫做泛型 * * 泛型:是一種廣泛的類型,把明確數(shù)據(jù)類型的工作提前到了編譯時(shí)期,借鑒了數(shù)組的特點(diǎn) * 泛型好處: * 避免了類型轉(zhuǎn)換的問題 * 可以減少黃色警告線 * 可以簡(jiǎn)化我們代碼的書寫 * * 什么時(shí)候可以使用泛型? * 問API,當(dāng)我們看到<E>,就可以使用泛型了 * */ public class GenericDemo { public static void main(String[] args) { //創(chuàng)建集合對(duì)象 Collection<Student> c = new ArrayList<Student>(); //創(chuàng)建元素對(duì)象 Student s = new Student("zhangsan",18); Student s2 = new Student("lisi",19); //添加元素對(duì)象 c.add(s); c.add(s2); //遍歷集合對(duì)象 Iterator<Student> it = c.iterator(); while(it.hasNext()) { //String str = (String)it.next(); //System.out.println(str); Student stu = it.next(); System.out.println(stu.name); } } } class Student { String name; int age; public Student(String name,int age) { this.name = name; this.age = age; } }
- 增強(qiáng)for
增強(qiáng)for循環(huán)是JDK1.5以后出來的一個(gè)高級(jí)for循環(huán),專門用來遍歷數(shù)組和集合的。它的內(nèi)部原理其實(shí)是個(gè)Iterator迭代器,所以在遍歷的過程中,不能對(duì)集合中的元素進(jìn)行增刪操作。
格式:
for(元素的數(shù)據(jù)類型 變量 : Collection集合or數(shù)組){
}
它用于遍歷Collection和數(shù)組。通常只進(jìn)行遍歷元素,不要在遍歷的過程中對(duì)集合元素進(jìn)行增刪操作。
- 案例代碼七:
package com.neuedu.demo; import java.util.ArrayList; import java.util.Collection; /* * foreach:增強(qiáng)for循環(huán),一般用于遍歷集合或者數(shù)組 * 格式: * for(元素的類型 變量 : 集合或者數(shù)組對(duì)象) { * 可以直接使用變量; * } * 注意:在增強(qiáng)for循環(huán)中不能修改集合,否則會(huì)出現(xiàn)并發(fā)修改異常。 * * public interface Iterable<T> * 實(shí)現(xiàn)這個(gè)接口允許對(duì)象成為 "foreach" 語句的目標(biāo)。 * */ public class ForEachDemo { public static void main(String[] args) { //創(chuàng)建集合對(duì)象 Collection<String> c = new ArrayList<String>(); //添加元素 c.add("hello"); c.add("world"); c.add("java"); //增強(qiáng)for循環(huán)遍歷集合 /*for(Object obj : c) { System.out.println(obj); }*/ /*for(String s : c) { System.out.println(s.toUpperCase()); }*/ for (String string : c) { c.add("android"); System.out.println(string); } } }
三、常見數(shù)據(jù)結(jié)構(gòu)
- 數(shù)組
數(shù)組,采用該結(jié)構(gòu)的集合,對(duì)元素的存取有如下的特點(diǎn):
查找元素快:通過索引,可以快速訪問指定位置的元素
增刪元素慢 ,每次添加元素需要移動(dòng)大量元素或這創(chuàng)建新的數(shù)組
數(shù)組.png
- 鏈表
鏈表,采用該結(jié)構(gòu)的集合,對(duì)元素的存取有如下的特點(diǎn):
- A:多個(gè)節(jié)點(diǎn)之間,通過地址進(jìn)行連接。例如,多個(gè)人手拉手,每個(gè)人使用自己的右手拉住下個(gè)人的左手,依次類推,這樣多個(gè)人就連在一起了。
- B:查找元素慢:想查找某個(gè)元素,需要通過連接的節(jié)點(diǎn),依次向后查找指定元素
C:增刪元素快:
增加元素:只需要修改連接下個(gè)元素的地址即可。
刪除元素:只需要修改連接下個(gè)元素的地址即可
鏈表.png
- 棧&隊(duì)列
- A:堆棧,采用該結(jié)構(gòu)的集合,對(duì)元素的存取有如下的特點(diǎn):
先進(jìn)后出(即,存進(jìn)去的元素,要在后它后面的元素依次取出后,才能取出該元素)。例如,子彈壓進(jìn)彈夾,先壓進(jìn)去的子彈在下面,后壓進(jìn)去的子彈在上面,當(dāng)開槍時(shí),先彈出上面的子彈,然后才能彈出下面的子彈。B:隊(duì)列,采用該結(jié)構(gòu)的集合,對(duì)元素的存取有如下的特點(diǎn):
先進(jìn)先出(即,存進(jìn)去的元素,要在后它前面的元素依次取出后,才能取出該元素)。例如,安檢。排成一列,每個(gè)人依次檢查,只有前面的人全部檢查完畢后,才能排到當(dāng)前的人進(jìn)行檢查。
棧和隊(duì)列.png
四、List子體系
- List子體系特點(diǎn)
- A:有序的(存儲(chǔ)和讀取的順序是一致的)
- B:有整數(shù)索引
- C:允許重復(fù)的
- List的特有功能
- void add(int index, E element) :將元素添加到index索引位置上
- E get(int index) :根據(jù)index索引獲取元素
- E remove(int index) :根據(jù)index索引刪除元素
- E set(int index, E element):將index索引位置的的元素設(shè)置為element
- 案例代碼八:
package com.neuedu.demo; import java.util.ArrayList; import java.util.List; /* * List: * 有序的(存儲(chǔ)和讀取的順序是一致的) * 有整數(shù)索引 * 允許重復(fù)的 * * List的特有功能: * void add(int index, E element) * E get(int index) * E remove(int index) * E set(int index, E element) * * 增刪改查 * */ public class ListDemo { public static void main(String[] args) { //創(chuàng)建的列表對(duì)象 List list = new ArrayList(); //void add(int index, E element) : 在指定索引位置添加指定元素 list.add(0, "hello"); list.add(0, "world"); list.add(1, "java"); //E get(int index) :根據(jù)索引返回元素 /*System.out.println(list.get(0)); System.out.println(list.get(1)); System.out.println(list.get(2));*/ //System.out.println(list.get(3)); /*for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); }*/ //E remove(int index) : 刪除指定元素并返回 //System.out.println(list.remove(5)); //E set(int index, E element) : 將指定索引位置的元素替換為指定元素,并將原先的元素返回 System.out.println(list.set(0, "android")); System.out.println(list); } }
- LinkedList特有功能
- LinkedList底層使用的是鏈表結(jié)構(gòu),因此增刪快,查詢相對(duì)ArrayList較慢
void addFirst(E e) :向鏈表的頭部添加元素
void addLast(E e):向鏈表的尾部添加元素
E getFirst():獲取鏈頭的元素,不刪除元素
E getLast():獲取鏈尾的元素,不刪除元素
E removeFirst():返回鏈頭的元素并刪除鏈頭的元素
E removeLast():返回鏈尾的元素并刪除鏈尾的元素
- 案例代碼九:
package com.neuedu.demo import java.util.LinkedList; /* * List的常用子類: * ArrayList * 底層是數(shù)組結(jié)構(gòu),查詢快,增刪慢 * LinkedList * 底層結(jié)構(gòu)是鏈表,查詢慢,增刪快 * * 如何選擇使用不同的集合? * 如果查詢多,增刪少,則使用ArrayList * 如果查詢少,增刪多,則使用LinkedList * 如果你不知道使用什么,則使用ArrayList * * LinkedList的特有功能: * void addFirst(E e) * void addLast(E e) * E getFirst() * E getLast() * E removeFirst() * E removeLast() * */ public class LinkedListDemo { public static void main(String[] args) { LinkedList list = new LinkedList(); list.add("hello"); list.add("world"); //void addFirst(E e) :將元素添加到索引為0的位置 //void addLast(E e) :將元素添加到索引為size()-1的位置 list.addFirst("java"); list.addLast("android"); //E getFirst() :獲取索引為0的元素 //E getLast() :獲取索引為size()-1的元素 //System.out.println(list.getFirst()); //System.out.println(list.getLast()); //E removeFirst() :刪除索引為0的元素并返回 //E removeLast() :刪除索引為size()-1的元素并返回 System.out.println(list.removeFirst()); System.out.println(list.removeLast()); System.out.println(list); } }
package com.neuedu.demo; import java.util.ArrayList; import java.util.List; /* * 需求:定義一個(gè)方法,返回指定列表中指定元素的索引位置 * * 判斷元素是否存在 * */ public class ListTest { public static void main(String[] args) { List list = new ArrayList(); list.add("hello"); list.add("world"); list.add("java"); //int index = index(list,"php"); //System.out.println(index); //boolean flag = contains(list, "php"); //System.out.println(flag); boolean flag = list.contains("php"); System.out.println(flag); } public static int index(List list,Object other) { for(int x = 0;x < list.size();x++) { //獲取列表中的元素 Object obj = list.get(x); //使用列表中的元素和指定的元素進(jìn)行比較 if(obj.equals(other)) { return x; } } //查找不到指定的元素 return -1; } public static boolean contains(List list,Object other) { //獲取指定元素在指定列表中的索引位置 int index = index(list,other); //如果索引位置大于等于0,則認(rèn)為元素存在,否則不存在 if(index >= 0) { return true; } else { return false; } } }



