1.1 集合概述
1.什麼是集合:
- 一個用來存儲多個元素的容器。
2.數組和集合的區別:
- 數組:長度固定,可以存儲基本數據類型 ,也可以存儲引用數據類型。
- 集合:長度可變,只能存儲引用數據類型,如果存儲基本數據類型則需要使用對應的包裝類。
3.集合的分類:
- 單列集合(Collection):每次存儲元素時只存儲一個元素。
- 雙列集合(Map):每次存儲元素時要 存儲兩個元素。
1.2 Collection集合體系
- Collection:父接口 所有單列集合的父類
- List:子接口
- ArrayList:實現類
- LinkedList:實現類
- Vector:實現類
- Set:子接口
- HashSet:實現類
- LinkedHashSet:實現類
- 其中,橙色框裏寫的都是接口類型,而藍色框裏填寫的都是具體的實現類。
- 集合本身是一個工具,它存放在Java.util包中。在Collection接口定義着單列集合框架中最共性的內容。
1.3 Collection常用方法
- public boolean add(E e):添加元素,添加成功返回true,否則false。
- public void clear():將集合元素清空。
- boolean remove(E e)
- 刪除指定元素,刪除成功返回true,否則false。
- 如果有多個相同的元素,默認只會刪除第一個。
- boolean contains(E e):判斷集合是否包含指定元素,包含返回true,否則false。
- public boolean isEmpty():判斷集合是否爲空(元素個數是否爲0),是返回true,否則false。
- public int size():獲得元素的個數。
- public Object[] toArray()
- 將集合中的元素添加到數組返回
- 集合轉數組
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class CollectionDemo01 {
public static void main(String[] args) {
//創建集合對象
Collection<String> coll=new ArrayList<String>();
//添加元素
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
System.out.println(coll);
//刪除元素
System.out.println(coll.remove("aaa"));// true
System.out.println(coll);
//判斷集合中是否包含元素
System.out.println(coll.contains("eeee"));//false
//集合轉數組
Object [] objs=coll.toArray();
//輸出數組中的元素
System.out.println(Arrays.toString(objs));//[bbb, ccc, ddd]
//清空集合元素
coll.clear();
System.out.println(coll);//[]
//判斷集合是否爲空
System.out.println(coll.isEmpty());//true
}
}
2.1 迭代器概述
1.什麼是迭代器?
- 一個用來遍歷集合的對象,該對象實現了Iterator接口
- 對Collection進行遍歷的迭代器
2.如何獲得迭代器對象?
- 通過集合對象調用該方法:Iterator<E> iterator()獲得迭代器對象。
3. Iterator接口常用方法?
- boolean hasNext() 判斷是否有下一個元素,有返回true,否則false
- E next() 先將指針下移指向下一個元素,並將當前指針指向位置的元素作爲返回值返回。
2.2 Iterator示例代碼
import java.util.ArrayList;
import java.util.Iterator;
public class IteratorDemo01 {
public static void main(String[] args) {
//創建集合對象
ArrayList<String> list=new ArrayList<>();
//添加元素
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
//使用普通for循環遍歷
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("--------------------");
//獲得迭代器對象
Iterator<String> it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
2.3 迭代器的好處
- 屏蔽了衆多集合的內部實現,對外提供統一的遍歷方式。
- 所有的單列集合都可以使用迭代器進行遍歷。
2.4 迭代器的注意事項
- hasNext方法僅僅是判斷是否有下一個元素,不會移動指針位置。
- hasNext方法和next方法必須成對出現,調用一次hasNext就對應一次next方法。
- 使用迭代器遍歷集合時不能對集合進行增刪操作,否則會拋出異常。
- java.util.ConcurrentModificationException: 併發修改異常
- 在使用迭代器遍歷集合的過程中對集合元素進行了增刪操作,則會拋出該異常。
3.1 增強for概述
1.增強for概述
- JDK1.5新特性
- 專門用來遍歷集合和數組
- 本質:迭代器
2.增強for格式
- for(數據類型 變量名:數組名或集合名){ //循環體}
3.2 增強for遍歷數組
public class ForEachDemo01 {
public static void main(String[] args) {
//定義數組
int [] arr={1,2,3,4,5,6};
//使用增強for遍歷數組
for(int num: arr){
System.out.println(num);
}
}
}
3.3 增強for遍歷集合
import java.util.ArrayList;
/*
增強for遍歷集合:存儲自定義對象
*/
public class ForEachDemo03 {
public static void main(String[] args) {
// 創建集合對象
ArrayList<Student> list = new ArrayList<>();
// 添加學生對象
list.add(new Student("小澤", 20));
list.add(new Student("小蒼", 24));
list.add(new Student("小波", 26));
list.add(new Student("小武", 28));
// 使用增強for
for (Student stu : list) {
System.out.println(stu);
// 修改姓名
stu.setName("lily");
}
System.out.println("----------");
// 使用增強for
for (Student stu : list) {
System.out.println(stu);
}
}
}
4.1 泛型在集合中的使用
- 創建集合同時指定集合存儲的數據類型
- 指定數據類型時,要麼指定左邊,要麼兩邊都執行相同的數據類型
- 在JDK1.7之前,必須兩邊都要指定並且要相同的數據類型
- 在JDK1.7之後,指定左邊即可
- 在泛型中沒有多態的概念
4.2 泛型在集合中使用的好處
- 將運行時錯誤轉換爲編譯期錯誤,增強了集合的安全性。
- 省去了數據類型強制轉換的麻煩。
- 示例代碼
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo04 {
public static void main(String[] args) {
//創建集合對象
ArrayList<String> list=new ArrayList<String>();
list.add("aa");
list.add("bb");
list.add("cc");
for(String str:list){
System.out.println(str.length());
}
}
}
4.3 泛型的定義與使用
1.泛型的概述
- JDK1.5新特性。
- 泛型可以使用在方法上,類上,接口上。
- 泛型變量可以理解爲是某種數據類型的佔位符。
- 泛型變量還可以理解爲是某種數據類型的變量。
- 泛型變量的命名規則:只要是合法的標識符就可以,一般使用一個大寫字母表示
a.常用的泛型變量名有:T type E element K key V value
2.泛型方法的概念
- 在定義方法時定義了泛型變量的方法就是泛型方法 。
3.泛型方法的定義格式
- 修飾符 <T> 返回值類型 方法名(參數列表){}
4.泛型方法的注意事項
- 泛型變量的具體數據類型是由調用者調用方法時傳參決定。
- 泛型變量的具體數據類型不能是基本數據類型,如果要使用基本數據類型則需要使用對應的包裝類類型。
- 泛型方法示例代碼1
public class Demo01 {
public static void main(String[] args) {
Integer in=test(456);
String str=test("bcd");
Student stu=test(new Student());
Double d=test(0.5);
int age=10;
System.out.println(age);
}
//泛型方法
public static <T> T test(T param){
T a=null;
return a;
}
}
- 泛型方法示例代碼2
/*
定義一個數組工具類MyArrays ,提供兩個成員方法,方法參數接收一個任意類型的數組
一個方法的功能是將數組的元素反轉.
一個方法的功能是將數組的元素拼接成一個字符串返回。
字符串格式:"[1,2,3,4,5]"
*/
public class MyArrays{
/*
使用泛型方法實現:方法參數接收一個任意類型的數組
一個方法的功能是將數組的元素反轉.
*/
public static <T> void reverse(T[] arr){
for(int i=0,j=arr.length-1;i<j;i++,j--){
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
/*
使用泛型方法:定義一個方法的功能:將數組的元素拼接成一個字符串返回。
字符串格式:"[1,2,3,4,5]"
*/
public static <T> String toString(T [] arr){
//創建可變字符串
StringBuilder sb=new StringBuilder("[");
//遍歷數組
for(T t:arr){
sb.append(t).append(",");
}
//刪除最後一個元素
sb.deleteCharAt(sb.length()-1);
sb.append("]");
return sb.toString();
}
}
4.4 泛型類
1. 泛型類概述
- 在定義類的同時定義了泛型變量的類。
2.泛型類的定義格式
- class 類名<T>{ // 在該類中可以將泛型變量T當成一種數據類型使用。 }
3.泛型類的注意事項
- 泛型類泛型變量的具體數據類型是在創建該類對象時由創建者指定。
- 如果創建泛型類對象時沒有指定泛型變量的具體數據類型,則默認是Object
- 靜態方法不能使用類上定義的泛型變量,如果該方法中要使用泛型變量,則需要將該定義爲泛型方法。
- 示例代碼
public class MyArrays<T>{
/*
方法參數接收一個任意類型的數組
一個方法的功能是將數組的元素反轉.
*/
public void reverse(T[] arr){
for(int i=0,j=arr.length-1;i<j;i++,j--){
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
/*
將數組的元素拼接成一個字符串返回。
字符串格式:"[1,2,3,4,5]"
*/
public String toString(T [] arr){
//創建可變字符串
StringBuilder sb=new StringBuilder("[");
//遍歷數組
for(T t:arr){
sb.append(t).append(",");
}
//刪除最後一個元素
sb.deleteCharAt(sb.length()-1);
sb.append("]");
return sb.toString();
}
}
//泛型類基本使用
public class Demo {
public static void main(String[] args) {
//定義字符串數組
String[] strs = {"a", "b", "c"};
//創建MyArrays對象
MyArrays<String> myArrays01=new MyArrays<>();
myArrays01.reverse(strs);
System.out.println(myArrays01.toString(strs));//[c,b,a]
//創建MyArrays對象
MyArrays<Integer> myArrays02=new MyArrays<>();
//創建整型數組
Integer[] arr={3,4,5,6,7,7};
myArrays02.reverse(arr);
System.out.println(myArrays02.toString(arr));//[7,7,6,5,4,3]
//創建MyArrays對象:不指定泛型變量的具體數據類型
MyArrays myArrays03=new MyArrays();
}
}
5.1 泛型接口
1. 泛型接口的概念
- 在定義接口的同時定義了泛型變量的接口
2.泛型接口的定義格式
- interface 接口名<T>{ // 可以將泛型變量T當成一種數據類型使用 }
3.泛型接口的實現方式
- 方式1:實現接口的同時指定泛型變量的具體數據類型。(不夠靈活)
- 方式2:實現接口的時不指定泛型變量的具體數據類型,那麼此時需要將該實現類定義爲泛型類 ,由使用者創建實現類對象時指定泛型變量的數據類型。(推薦使用)
- 泛型接口示例代碼
/*
分層開發:
1.表現層
2.業務層
3.數據訪問層:直接和數據庫打交道,對數據庫進行增刪改查操作。
*/
public interface Dao<T> {
//增
public void save(T t);
//刪
public void delete(int id);
//改
public void update(T t);
//查
public T find(int id);
}
/*
方式1:實現接口的同時指定泛型變量的具體數據類型。
*/
public class ProductDao implements Dao<Product> {
@Override
public void save(Product product) {
System.out.println("增加產品");
}
@Override
public void delete(int id) {
}
@Override
public void update(Product product) {
}
@Override
public Product find(int id) {
return null;
}
}
/*
方式1:實現接口的同時指定泛型變量的具體數據類型。
*/
public class StudentDao implements Dao<Student> {
@Override
public void save(Student student) {
System.out.println("保存學生信息");
}
@Override
public void delete(int id) {
System.out.println("刪除學生信息");
}
@Override
public void update(Student student) {
System.out.println("更新學生信息");
}
@Override
public Student find(int id) {
System.out.println("查找學生信息");
return null;
}
}
/*
實現接口的時不指定泛型變量的具體數據類型,那麼此時需要將該實現類定義爲泛型類,
由使用者創建實現類對象時指定泛型變量的數據類型。
*/
public class BaseDao<T> implements Dao<T> {
@Override
public void save(T t) {
}
@Override
public void delete(int id) {
}
@Override
public void update(T t) {
}
@Override
public T find(int id) {
return null;
}
}
public class Demo {
public static void main(String[] args) {
//創建學生對象
Student stu=new Student();
//創建StudentDao對象
StudentDao stuDao=new StudentDao();
stuDao.save(stu);
stuDao.update(stu);
stuDao.delete(1);
stuDao.find(2);
//創建產品對象
Product p=new Product();
//創建ProduceDao對象
ProductDao pd=new ProductDao();
pd.save(p);
// 創建BaseDao對象指定泛型變量是Student
BaseDao<Student> baseDao=new BaseDao<>();
baseDao.save(stu);
// 創建BaseDao對象指定泛型變量是Product
BaseDao<Product> baseDao2=new BaseDao<>();
baseDao2.save(p);
}
}
6.1 泛型上下限
6.1.1 泛型上下限的引入
需求1:
- 定義一個方法可以接收任意類型的集合對象
- 集合對象只能存儲Integer或者是Integer的父類數據
需求2:
- 定義一個方法可以接收任意類型的集合對象
- 集合對象只能存儲Number或者是Number的子類數據
6.1.2 泛型上下限的格式
1.泛型的上限
- 格式:<? extends 類>
- 意義:只能接收該類型及其子類
2.泛型的下限
- 格式:<? super類>
- 意義:只能接收該類型及其父類型
- 注意事項
- ? 代表泛型通配符,可以匹配任意的類型。
- 通配符?不能用在泛型方法、泛型類、泛型接口定義上。
- 通配符?一般不會單獨使用,一般都會配合泛型上下限使用。
- ? 不能在方法體中當成一種數據類型使用
a.泛型上限
? extends Number:可以接收Number或Number子類類型的數據
b.泛型下限
? super Integer : 可以接收Integer或Integer父類類型的數據
import java.util.ArrayList;
public class Demo05 {
public static void main(String[] args) {
ArrayList<Number> list01=new ArrayList<>();
ArrayList<Integer> list02=new ArrayList<>();
ArrayList<Object> list03=new ArrayList<>();
print01(list01);
print01(list02);
print01(list03);
print02(list01);
print02(list02);
//print02(list03);
}
/*
需求2:定義一個方法可以接收任意類型的集合對象
集合對象只能存儲Number或者是Number的子類數據
*/
public static void print02(ArrayList<? extends Number> list){
}
/*
需求1:定義一個方法可以接收任意類型的集合對象
集合對象只能存儲Integer或者是Integer的父類數據
*/
public static void print01(ArrayList<? super Integer> list){
}
}