泛型
package com.oracle.demo01;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Demo01 {
public static void main(String[] args) {
Map<String, String> map=new HashMap<>();
map.put("欣欣", "萌萌");
map.put("萌萌", "欣欣");
map.put("小欣", "小萌");
Set<String> set1=map.keySet();
Iterator<String> it=set1.iterator();
while (it.hasNext()) {
String key=it.next();
String value=map.get(key);
System.out.println(key+" "+value);
}
}
}
運行結果:
1.1 泛型通配符
泛型是在限定數據類型,當在集合或者其他地方使用到泛型后,那么這時一旦明確泛型的數據類型,那么在使用的時候只能給其傳遞和數據類型匹配的類型,否則就會報錯。
調用方法:
Collection<Student> list = new ArrayList<Student>();
printCollection(list);
實現了可迭代任意元素類型集合的方法
public static void printCollection(Collection<?> list) {
Iterator<?> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
總結:
當使用泛型類或者接口時,傳遞的數據中,泛型類型不確定,可以通過通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object類中的共性方法,集合中元素自身方法無法使用。
1.2 泛型限定
限定泛型的上限:
格式:? extends E
? 代表接收E類型或者E的子類型的元素
例如,泛型限定為:? extends Person
則 ? 代表接收Person類型或者Person子類型的元素
限定泛型的下限:
格式:? super E
? 代表接收E類型或者E的父類型的元素
例子:修改下面的方法,使該方法可以打印學生和工人的集合
class Student extends Person{ }
class Worker extends Person{ }
public static void printCollection(Collection<?> list) {
Iterator<?> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}}
找到學生和工人的共性類型Person。那么,泛型的限定可以這樣書寫:
? extends Person : 接收Person類型或者Person的子類型。修改方法如下:
public static void printCollection(Collection<? extends Person> list) {
Iterator<? extends Person> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
package com.oracle.arraylist;
public class Emp {
private String name;
private int 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;
}
}
package com.oracle.arraylist;
public class Chushi extends Emp {
}
package com.oracle.arraylist;
public class FuWuYuan extends Emp {
}
package com.oracle.arraylist;
public class Manager extends Emp{
}
package com.oracle.arraylist;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class Test {
public static void main(String[] args) {
ArrayList<Chushi> arr=new ArrayList<Chushi>();
HashSet<FuWuYuan> set=new HashSet<FuWuYuan>();
ArrayList<Manager> arr2=new ArrayList<Manager>();
}
//寫一個通用方法來遍歷這三個集合
//泛型沒有多態這一說法<E> E
//泛型限定符 ?
public static void get(Collection<? extends Emp> coll){
}
}
List接口
Collection中的常用幾個子類(List集合、Set集合)
2.1 List接口介紹
有序的 collection(也稱為序列)用戶可以對列表中每個元素的插入位置進行精確地控制。用戶可以根據元素的整數索引(在列表中的位置)訪問元素,並搜索列表中的元素。與 set 不同,列表通常允許重復的元素。
總結:
List接口:
- 1. 是一個元素存取有序的集合
- 2. 是一個帶有索引(下標)的集合,通過索引就可以精確的操作集合中的元素
- 3. 集合中可以有重復的元素,通過元素的equals方法,來比較是否為重復的元素
List接口的常用子類有:
ArrayList集合
LinkedList集合
2.2 List接口中常用的方法
增加元素方法
add(Object e):向集合末尾處,添加指定的元素
add(int index, Object e):向集合指定索引處,添加指定的元素,原有元素依次后移
刪除元素刪除
remove(Object e):將指定元素對象,從集合中刪除,返回值為被刪除的元素
remove(int index):將指定索引處的元素,從集合中刪除,返回值為被刪除的元素
替換元素方法
set(int index, Object e):將指定索引處的元素,替換成指定的元素,返回值為替換前的元素
查詢元素方法
get(int index):獲取指定索引處的元素,並返回該元素
package com.oracle.List;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class Demo01 {
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add(1,"e");
//遍歷
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
//刪除指定位置上的元素
list.remove(0);//0為下標
System.out.println("=========");
//遍歷
for(String i : list){
System.out.println(i);
}
System.out.println("======================");
//修改指定位置上的元素
list.set(1, "你好嗎?");
Iterator<String> it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
運行結果:
2.2.1 Iterator的並發修改異常
並發修改異常解決辦法:在迭代時,不要使用集合的方法操作元素。
那么想要在迭代時對元素操作咋辦?通過ListIterator迭代器操作元素是可以的,ListIterator的出現,解決了使用Iterator迭代過程中可能會發生的錯誤情況。
2.3 List集合存儲數據的結構
堆棧,采用該結構的集合,對元素的存取有如下的特點:
先進后出(即,存進去的元素,要在它后面的元素依次取出后,才能取出該元素)。例如,子彈壓進彈夾,先壓進去的子彈在下面,后壓進去的子彈在上面,當開槍時,先彈出上面的子彈,然后才能彈出下面的子彈。
棧的入口、出口的都是棧的頂端位置
壓棧:就是存元素。即,把元素存儲到棧的頂端位置,棧中已有元素依次向棧底方向移動一個位置。
彈棧:就是取元素。即,把棧的頂端位置元素取出,棧中已有元素依次向棧頂方向移動一個位置。
特點:先進后出
隊列,采用該結構的集合,對元素的存取有如下的特點:
先進先出(即,存進去的元素,要在后它前面的元素依次取出后,才能取出該元素)。例如,安檢。排成一列,每個人依次檢查,只有前面的人全部檢查完畢后,才能排到當前的人進行檢查。
隊列的入口、出口各占一側。例如,下圖中的左側為入口,右側為出口。
數組,采用該結構的集合,對元素的存取有如下的特點:
查找元素快:通過索引,可以快速訪問指定位置的元素
增刪元素慢:
指定索引位置增加元素:需要創建一個新數組,將指定新元素存儲在指定索引位置,再把原數組元素根據索引,復制到新數組對應索引的位置。如下圖
指定索引位置刪除元素:需要創建一個新數組,把原數組元素根據索引,復制到新數組對應索引的位置,原數組中指定索引位置元素不復制到新數組中。如下圖
鏈表,采用該結構的集合,對元素的存取有如下的特點:
多個節點之間,通過地址進行連接。例如,多個人手拉手,每個人使用自己的右手拉住下個人的左手,依次類推,這樣多個人就連在一起了。
查找元素慢:想查找某個元素,需要通過連接的節點,依次向后查找指定元素
增刪元素快:
增加元素:操作如左圖,只需要修改連接下個元素的地址即可。
刪除元素:操作如右圖,只需要修改連接下個元素的地址即可。
2.4 ArrayList集合
arrayList集合數據存儲的結構是數組結構。元素增刪慢,查找快,由於日常開發中使用最多的功能為查詢數據、遍歷數據,所以ArrayList是最常用的集合。
LinkedList集合(list的子接口)
LinkedList集合數據存儲的結構是鏈表結構。方便元素添加、刪除的集合。實際開發中對一個集合元素的添加與刪除經常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。
2.5 Vector集合(枚舉Enumeration)
Vector集合數據存儲的結構是數組結構,Vector中提供了一個獨特的取出方式,就是枚舉Enumeration,它其實就是早期的迭代器Vector集合已被ArrayList替代
Vector常見的方法:
Enumeration枚舉常見的方法:
Vector集合對ArrayList集合使用的對比