1集合java
集合是java中提供的一種容器,能夠用來存儲多個數據。數組
數組的長度是固定的。集合的長度是可變的。集合中存儲的元素必須是引用類型數據。this
1.1ArrayList集合存儲元素(複習)spa
例:3d
public class Person { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } 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; } public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
import java.util.ArrayList; public class Test1 { public static void main(String[] args) { //集合複習:存儲基本數據類型 ArrayList<Double> arr1=new ArrayList<Double>(); arr1.add(1.6); arr1.add(2.3); arr1.add(3.6); for(int i=0;i<arr1.size();i++){ System.out.print(arr1.get(i)+" "); } System.out.println(); //集合存儲引用數據類型 ArrayList<Person> arr2=new ArrayList<Person>(); arr2.add(new Person("張三",18));//存匿名對象 arr2.add(new Person("小紅帽",8)); arr2.add(new Person("大灰狼",55)); for(int i=0;i<arr2.size();i++){ System.out.println(arr2.get(i)); //調用toString方法,已重寫 } } }
1.2集合的繼承實現關係指針
經常使用的:code
1.3 Collection接口對象
Collection接口是集合中的頂層接口,它中定義的全部功能子類均可以使用。blog
Collection 是層次結構中的根接口。Collection 表示一組對象,這些對象也稱爲 collection 的元素。一些 collection 容許有重複的元素,而另外一些則不容許。一些 collection 是有序的,而另外一些則是無序的。排序
(這裏的有序不是指元素在值上的排序,而是指存、取的順序一致,怎麼存就怎麼取,有索引下標)
1.3.1 Collection經常使用方法
Collection是接口,因此全是抽象方法。
須要用多態new對象。
例:
import java.util.Collection; import java.util.ArrayList; public class CollectionTest { public static void main(String[] args) { //建立對象 Collection<String> col=new ArrayList<String>(); //添加元素 col.add("中國"); col.add("你好"); col.add("java"); //判斷集合中是否包含某元素 boolean flag=col.contains("java"); if(flag){ System.out.println("true,包含元素"); } //移除元素 boolean dels=col.remove("你好"); //這個是返回布爾值 if(dels){ System.out.println("移除成功"); } //向下轉型 ArrayList<String> arr=null; //定義成全局,否則遍歷時取不到 if(col instanceof ArrayList){ arr=(ArrayList<String>)col; } System.out.println(); //遍歷 System.out.println("遍歷結果:"); for(int i=0;i<arr.size();i++){ System.out.print(arr.get(i)+" "); } System.out.println(); System.out.println(); //轉成數組 Object[] strs=col.toArray(); System.out.println("遍歷數組:"); for(int i=0;i<strs.length;i++){ //String str=(String)strs[i];//這裏是Object型數組,若是想轉成String數組,不能直接強轉,要給元素轉型 System.out.print(strs[i]+" "); } System.out.println(); System.out.println(); //清除內容 col.clear(); System.out.println("清除後:"); for(int i=0;i<arr.size();i++){ System.out.print(arr.get(i)+" "); } } }
注意:
1注意方法的返回值類型
2必定要指定泛型,否則還要強轉
例:會有警告
1.4 Iterator迭代器
1.4.1定義
java中提供了不少個集合,它們在存儲元素時,採用的存儲方式不一樣。
List有序(有下標索引),set無序(看上面的繼承體系圖)
要取出這些集合中的元素,可經過一種通用的獲取方式來完成。
迭代定義:
Collection集合元素的通用獲取方式:在取元素以前先要判斷集合中有沒有元素,若是有,就把這個元素取出來,繼續再判斷,若是還有就再取出出來。一直把集合中的全部元素所有取出。這種取出方式專業術語稱爲迭代。
集合中把這種取元素的方式描述在Iterator接口中。
1.4.2 Iterator接口的經常使用方法
hasNext()方法:用來判斷集合中是否有下一個元素能夠迭代。若是返回true,說明能夠迭代。
next()方法:用來返回迭代的下一個元素,並把指針向後移動一位。
1.4.3 Iterator接口的對象
Iterable對象裏有一個iterator() 方法,能夠返回Iterator對象,Collection繼承了這個方法,那麼其子類或實現類就都有了這個方法,能夠用這個方法建立Iterator對象。
例:(Iterator接口也可使用<>來控制迭代元素的類型的)
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class IteratorTest { public static void main(String[] args) { Collection<Integer> col=new ArrayList<Integer>(); col.add(1); col.add(2); col.add(3); col.add(4); //獲取迭代器對象 Iterator<Integer> it=col.iterator(); //循環 while(it.hasNext()){ int i=it.next(); //自動拆箱 System.out.println(i); } } }
注意:
1)next()只能用一次,再調用,指針還會日後走,想判斷,要先把值獲取到,再判斷值。
例:
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class I2 { public static void main(String[] args) { Collection<Integer> col=new ArrayList<Integer>(); col.add(1); col.add(2); col.add(3); col.add(4); //獲取迭代器對象 Iterator<Integer> it=col.iterator(); //用循環 while(it.hasNext()){ if(it.next()==2){ System.out.println(it.next()); } } } }
說明next()又向後走了,因此要改爲這樣:
while(it.hasNext()){ int i=it.next(); if(i==2){ System.out.println(i); } }
還能夠for循環,但不經常使用
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class I2 { public static void main(String[] args) { Collection<Integer> col=new ArrayList<Integer>(); col.add(1); col.add(2); col.add(3); col.add(4); for(Iterator<Integer> it=col.iterator();it.hasNext();){ System.out.println(it.next()); } } }
2)在進行集合元素取出時,若是集合中已經沒有元素了,還繼續使用迭代器的next方法,將會發生java.util.NoSuchElementException沒有集合元素的錯誤。
例:
1.5集合元素的向下轉型
集合中能夠存儲任何對象,那麼存放進去的數據就再也不是原來的類型了,而是提高成了Object。
若是集合中存放的是多個對象,這時進行向下轉型會發生類型轉換異常。
3加強for循環
加強for循環是JDK1.5之後出來的一個高級for循環,專門用來遍歷數組和集合的。它的內部原理實際上是個Iterator迭代器,因此在遍歷的過程當中,不能對集合中的元素進行增刪操做。
3.1格式:
for(元素的數據類型 變量 : Collection集合or數組){
}
例:
import java.util.ArrayList; import java.util.Collection; public class forTest { public static void main(String[] args) { Collection<String> col=new ArrayList<String>(); col.add("你好"); col.add("快樂"); //使用加強for for(String str:col){ System.out.println(str); //取到的就是String對象 } //使用加強for遍歷數組 int[] arr={1,2,3,4,5}; for(int i:arr){ System.out.print(i+" "); //i就是每一個值 } } }
3.2對比:
1)迭代器只能迭代集合,加強for能遍歷集合和數組。
2)新for循環必須有被遍歷的目標。目標只能是Collection或者是數組。只用來遍歷,不進行任何操做。
遍歷數組時,若是僅爲遍歷,可使用加強for。
若是要對數組的元素進行操做,使用老式for循環,(由於能夠經過下標操做)
3.3總結:
遍歷集合:三種方式
遍歷數組:兩種方式
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Test1 { public static void main(String[] args) { showList(); showArr(); } public static void showList(){ Collection<String> col=new ArrayList<String>(); col.add("abc"); col.add("ABC"); col.add("12345"); //for循環遍歷 System.out.println("for循環遍歷集合:"); ArrayList<String> arr=null; if(col instanceof ArrayList){ arr=(ArrayList<String>)col; } for(int i=0;i<arr.size();i++){ System.out.print(arr.get(i)+"\t"); } //迭代器 System.out.println(); System.out.println("迭代器集合:"); Iterator<String> it=col.iterator(); while(it.hasNext()){ System.out.print(it.next()+"\t"); } //加強for System.out.println(); System.out.println("加強for遍歷集合:"); for(String str:col){ System.out.print(str+"\t"); } } public static void showArr(){ System.out.println(); int[] arr={1,2,3,4,5}; System.out.println("普通for遍歷數組:"); for(int i=0;i<arr.length;i++){ System.out.print(arr[i]+" "); } System.out.println(); System.out.println("加強for遍歷數組:"); for(int i:arr){ System.out.print(i+" "); } } }
4泛型
前面一些例子,集合中是能夠存聽任意對象的,提高成Object類型,這時容易發生
ClassCastException類型轉換異常,泛型就是爲了解決這個問題。
4.1定義
使用集合時,必須明確集合中元素的類型,這種方式稱爲泛型。
泛型,用來靈活地將數據類型應用到不一樣的類、方法、接口當中。將數據類型做爲參數進行傳遞。
定義格式:
修飾符 class 類名<表明泛型的變量> { }
修飾符 interface接口名<表明泛型的變量> { }
E就是一個變量,是element的意思,在何時明確:
1)實現或繼承時明確
Public class MyList<String> implements list<E>{}
Public class MyList<E> implements list<String>{}
2)new對象時明確
Api中帶<E>的方法都是如此
4.2使用泛型的好處
將運行時期的ClassCastException,轉移到了編譯時期變成了編譯失敗。避免了類型強轉的麻煩。
Tips:
泛型:又叫僞泛型,編譯時不進.class文件 (註釋也不進)
只在java代碼中對集合存儲數據類型進行約束
4.3泛型通配符
當定義方法時,沒法肯定具體集合中的元素類型是什麼,可使用泛型通配符<?>,用來佔空。
例:
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class Test02 { public static void main(String[] args) { ArrayList<String> arr=new ArrayList<String>(); arr.add("中國"); arr.add("java"); HashSet<Integer> set=new HashSet<Integer>(); set.add(1); set.add(2); showAll(arr); showAll(set); } //泛型通配符 public static void showAll(Collection<?> col){ Iterator<?> it=col.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
可是一旦使用泛型的通配符後,只能使用Object類中的共性方法,集合中元素自身方法沒法使用。(能夠向下轉型,可是太麻煩了)
4.4泛型限定
泛型裏面沒有向上向下轉型的概念。因此要定好。
限定泛型的上限:
格式:? extends E
? 表明接收E類型或者E的子類型的元素
限定泛型的下限:
格式:? super E
? 表明接收E類型或者E的父類型的元素(父類型,不僅是父類)
例:
//員工類 public abstract class Emp { public abstract void work(); }
//經理類 public class Manager extends Emp{ public void work() { System.out.println("經理管理"); } }
//服務員類 public class Waiter extends Emp{ public void work() { System.out.println("服務員上菜"); } }
//廚師類 public class Cooker extends Emp{ public void work() { System.out.println("廚師炒菜"); } }
import java.util.ArrayList; public class Test03 { //四個類:員工,經理,服務員,廚師 都有work方法 //傳入三個類調用其work方法 public static void main(String[] args) { Manager m=new Manager(); ArrayList<Manager> arr1=new ArrayList<Manager>(); arr1.add(m); Waiter w=new Waiter(); ArrayList<Waiter> arr2=new ArrayList<Waiter>(); arr2.add(w); Cooker c=new Cooker(); ArrayList<Cooker> arr3=new ArrayList<Cooker>(); arr3.add(c); working(arr1); working(arr2); working(arr3); ArrayList<Object> arr4=new ArrayList<Object>(); arr4.add("這是一個Object類型的數據"); arr4.add("這是一個Object類型的數據2"); working2(arr4); } public static void working(ArrayList<? extends Emp> arr){ //限定泛型的上限 Emp emp=arr.get(0); emp.work(); } public static void working2(ArrayList<? super Emp> arr){ //限定泛型的下限 for(int i=0;i<arr.size();i++){ System.out.println(arr.get(i)); } } }
這裏若是是接口,也能夠用extends。