[AppleScript] 纯文本查看 复制代码
day02【Collection、泛型】
## 主要内容
- Collection集合
- 迭代器(遍历集合)
- 增强for(foreach)
- 泛型
## 教学目标
- [ ] 能够说出集合与数组的区别
- [ ] 说出Collection集合的常用功能
- [ ] 能够使用迭代器对集合进行取元素
- [ ] 能够说出集合的使用细节
- [ ] 能够使用集合存储自定义类型
- [ ] 能够使用foreach循环遍历集合
- [ ] 能够使用泛型定义集合对象
- [ ] 能够理解泛型上下限
- [ ] 能够阐述泛型通配符的作用
# 第一章 Collection 集合
## 1.1 集合概述
```java
什么是集合
* 就是一个容器,可以存储多个数据。
数组和集合的区别
* 数组的长度固定,集合的长度是可变。
* 数组可以存储基本数据类型,也可以存储引用数据类型,集合只能存储引用数据类型
* 数组只能存储同一种数据类型,而集合可以存储多种数据类型(不建议)
集合的分类
* 单列集合:Collection:每次存储元素时只存储一个
* 双列集合:Map:每次存储元素时存储两个元素。
```
## 1.2 Collection集合体系
```java
* Colletion:是所有单列的集合的父类。
* List
* ArrayList
* LinkedList
* Vector(过时了)
* Set
* HashSet
* LinkedHashSet
```
## 1.3 Collection 常用方法
```java
public boolean add(E e) 添加元素
public void clear() 清空集合中的元素
boolean remove(E e) 删除指定的元素,删除成功返回true,否则false,只删除第一次出现的元素。
boolean contains(E e) 判断集合中是否包含指定的元素,包含返回true,否则false
public boolean isEmpty() 判断集合是否为空(元素个数是否等于零),为空返回true,否则false
public int size() 获得集合元素的个数
public Object[] toArray() 将集合转换为数组
```
- 示例代码
```java
public class CollectionDemo02 {
public static void main(String[] args){
// 创建集合对象
Collection<String> co = new ArrayList<>();
// 添加元素
co.add("aa");
co.add("bb");
co.add("cc");
co.add("aa");
System.out.println(co); // [aa, bb, cc, aa]
// 集合转数组
Object[] objs = co.toArray();
System.out.println(Arrays.toString(objs)); // [aa, bb, cc, aa]
// 删除指定元素:aa
System.out.println(co.remove("aa")); // true
System.out.println(co);
// 判断集合中是否包含元素:aa
System.out.println(co.contains("aa")); // false
// 清空集合中的元素
co.clear();
/*co.add("dd");*/
System.out.println(co);
// 判断集合是否为空
System.out.println(co.isEmpty());
if (co.isEmpty()){
}
}
}
```
## 1.4 使用集合存储自定义对象
# 第二章 Iterator迭代器
### 2.1 什么是迭代器
```java
什么是迭代器
* 一个用来遍历集合的对象,该对象是实现了Iterator接口。
* 只要是实现了Iterator接口的对象都是迭代器对象。
如何获得迭代器
* 通过调用集合对象的该方法:Iterator<E> iterator()
Iterator接口中的常用方法
* boolean hasNext(); 判断是否有下一个元素,如果有则返回true,否则false
* E next(); 先将指针下移指向下一个元素,然后将当前指针指向位置的元素作为返回值。
迭代器的使用注意事项
* java.util.NoSuchElementException:没有元素异常
* 如果没有元素可迭代了仍然调用next方法获得元素,则会抛出该异常。
```
### 2.2 迭代器的好处
```java
1. 屏蔽了众多集合的内部实现,对外提供统一的遍历方式。
2. 只要是单列集合都可以使用迭代器遍历
```
### 2.3 Iterator常用方法
```java
* boolean hasNext(); 判断是否有下一个元素,如果有则返回true,否则false
* E next(); 先将指针下移指向下一个元素,然后将当前指针指向位置的元素作为返回值。
```
### 2.4 Iterator示例代码
```java
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");
// 使用循环改进
Iterator<String> it = list.iterator();
while(it.hasNext()){ // true
System.out.println(it.next());
}
/* 没有使用循环
// 使用迭代器遍历集合
Iterator<String> it = list.iterator(); // new Itr();
System.out.println(it.hasNext()); // true
System.out.println(it.next()); // aa
System.out.println(it.hasNext()); // true
System.out.println(it.next()); // bb
System.out.println(it.hasNext()); // true
System.out.println(it.next()); // cc
System.out.println(it.hasNext()); // true
System.out.println(it.next()); // dd
System.out.println(it.hasNext()); // false
System.out.println(it.next()); // dd
*/
// 普通for遍历
/* for(int index = 0;index < list.size();index++){
// 根据索引获得集合
String str = list.get(index);
System.out.println(str);
}*/
}
}
```
![](/Users/pkxing/Documents/88期就业班/就业班-day02-Collection、泛型/笔记/迭代器遍历集合.png)
# 第三章 增强for(foreach)
### 3.1 增强for概述
```java
* JDK1.5新特性
* 专门用来遍历集合和数组的
* 本质:迭代器
```
### 3.2 增强for格式
```java
for(数据类型 变量名: 数组名或集合名){
}
```
### 3.3 增强for示例代码
#### 练习1:遍历数组
```java
public class ForEachDemo01 {
public static void main(String[] args){
// 定义一个整型数组
int[] arr = {1,2,3,4,5,6};
// 使用增强for遍历数组
/*
for(数据类型 变量名: 数组名或集合名){
}
*/
for (int num : arr){
System.out.println(num);
num += 10;
}
System.out.println("------------");
for(int num:arr){
System.out.println(num);
}
}
}
```
![](/Users/pkxing/Documents/88期就业班/就业班-day02-Collection、泛型/笔记/增强for遍历数组.png)
#### 练习2:遍历集合
```java
public class ForEachDemo02 {
public static void main(String[] args){
// 增强for遍历集合:集合存储自定义对象
test01();
// 增强for遍历集合:集合存储字符串
test02();
}
/*
增强for遍历自定义对象
*/
public static void test02(){
// 创建集合对象
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("小泽"));
list.add(new Student("小苍"));
list.add(new Student("小波"));
list.add(new Student("小玉玉"));
// 使用增强for遍历
for(Student stu: list){
System.out.println(stu);
stu.setName("小野");
}
System.out.println("-------------");
// 使用增强for遍历
for(Student stu: list){
System.out.println(stu);
}
}
// 增强for遍历集合
public static void test01(){
// 创建集合对象
ArrayList<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
for(String str: list){
System.out.println(str);
}
}
}
```
###
# 第四章 泛型
## 3.1 泛型在集合中使用
```java
泛型的概述
* JDK1.5新特性。
* 泛型可以使用在方法中,类上,接口上。
泛型在集合中使用的好处
* 将运行期错误转换为编译器错误,增强了集合的安全性。
* 避免了类型强制转换的麻烦。
泛型在集合中的使用注意事项
* 在泛型中,没有多态的概念,要么指定左边,要么两边都指定相同的数据类型。
* 在JDK1.7之前,必须两边都指定相同的数据类型。
```
- 示例代码
```java
public class CollectionDemo {
public static void main(String[] args){
// 创建集合对象
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
// list.add(123);
for(String str:list){
System.out.println(str.length());
}
// 遍历集合
for (Object obj:list) {
// 向下转型为字符串
String str = (String) obj;
System.out.println(str.length());
}
}
}
```
## 3.2 泛型的定义与使用(了解)
### 3.2.1 泛型方法
#### 泛型方法引入
- 定义一个方法接收一个任意类型的参数,返回值类型与实际参数类型一致。
```java
什么是泛型
* 数据类型参数化。
泛型方法的引入
* 定义一个方法接收一个任意类型的参数,返回值类型与实际参数类型一致。
泛型的概述
* JDK1.5新特性。
* 泛型可以使用在方法中,类上,接口上。
* 泛型变量可以理解为是一种数据类型的占位符。
* 泛型变量还可以理解为一种数据类型的变量。
* 泛型变量的命名规则:只要是合法的标识符就可以,一般会使用一个大写字母表示
常用的泛型变量的名字:T, K, V,E
泛型方法的概念
* 在定义方法时定义了泛型变量的方法则称为泛型方法。
泛型方法的定义格式
* 修饰符 <T> 返回值类型 方法名(参数列表){}
泛型方法的注意事项
* 泛型变量的具体数据类型是在调用该方法时由调用者传递参数决定。
* 参数是什么类型,则泛型变量的具体数据类型就是什么类型。
* 泛型变量的具体数据类型不能是基本数据类型,如果要使用基本数据类型,要使用对应的包装类类型。
```
#### 示例代码
```java
public class Demo01 {
public static void main(String[] args){
String str = test("abc");
Integer in = test(123);
Student stu = test(new Student());
int age = 100;
System.out.println(age);
}
public static void sum(int a,int b){
}
/*
泛型方法
*/
public static <T> T test(T param){
return param;
}
}
```
#### 泛型方法练习
```java
- 定义一个数组工具类MyArrays
- 提供两个成员方法,方法参数接收一个任意类型的数组
- 一个方法的功能是将数组的元素反转.
- 一个方法的功能是将数组的元素拼接成一个字符串返回。
- 字符串格式:"[1,2,3,4,5]"
```
- 代码实现
```java
/**
- 提供两个成员方法,方法参数接收一个任意类型的数组
- 一个方法的功能是将数组的元素反转.
- 一个方法的功能是将数组的元素拼接成一个字符串返回。
- 字符串格式:"[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;
arr = 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();
}
}
public class Demo02 {
public static void main(String[] args){
// 创建字符串数组
String[] strs = {"a","b","c"};
// 创建整型数据
Integer[] arr = {1,2,3,4,5,6};
/*
// 创建数据工具类型对象
MyArrays myArrays = new MyArrays();
myArrays.reverse(strs);*/
System.out.println("反转前:"+ Arrays.toString(strs));
// 反转字符串数组元素
MyArrays.reverse(strs);
System.out.println("反转后:" + MyArrays.toString(strs));
System.out.println("反转前:"+MyArrays.toString(arr));
// 反转整型数组元素
MyArrays.reverse(arr);
System.out.println("反转后:"+MyArrays.toString(arr));
}
}
```
### 3.2.2 泛型类
```java
什么是泛型类
* 在类定义时定义了泛型变量的类就是泛型类
泛型类的定义格式
* class 类名<T>{
// 可以将泛型变量T当成一种数据类型使用
}
泛型类的注意事项
* 泛型变量的具体数据类型是由创建对象时由使用者决定,如果没有指定具体数据类型则默认是Object
* 静态方法不能使用类上定义的泛型变量,如果该方法要使用泛型变量,则需要将该方法定义为泛型方法。
```
- 示例代码
```java
/**
泛型类定义
*/
public class MyArrays<T>{
// 一个方法的功能是将数组的元素反转.
public static <T> void reverse(T[] arr){
for(int i = 0,j = arr.length - 1; i < j; i++,j--){
T temp = arr;
arr = 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 void xxx(){
}
}
public class Demo01 {
public static void main(String[] args){
// 创建字符串数组
String[] strs = {"a","b","c"};
// 创建整型数据
Integer[] arr = {1,2,3,4,5,6};
// 创建泛型类对象
MyArrays<String> myArrays01 = new MyArrays<>();
// 此时通过对象myArrays01调用方法,方法中的泛型变量的具体数据类型是:String
myArrays01.reverse(strs);
// 创建泛型类对象
MyArrays<Integer> myArrays02 = new MyArrays<>();
// 此时通过对象myArrays02调用方法,方法中的泛型变量的具体数据类型是:Integer
myArrays02.reverse(arr);
MyArrays myArrays03 = new MyArrays();
}
}
```
### 3.2.3 泛型接口
```java
什么是泛型接口
* 在定义接口的同时定义了泛型变量的接口
泛型接口的定义格式
* interface 接口名<T>{
// 将泛型变量T当成一种数据类型使用
}
泛型接口的实现方式
* 方式1:实现接口的同时指定泛型变量的具体数据类型(不推荐使用,不够灵活)
* 方法2:实现接口时不指定泛型变量的具体数据类型,将实现类定义为泛型类,
由使用者创建泛型类对象时指定泛型变量的具体数据类型。(推荐使用)
```
- 示例代码
```java
/**
Dao:数据访问层接口
泛型接口
表现层
业务层
数据访问层:直接跟数据库打交道,对数据库执行增删改查操作的。
*/
public interface Dao<T>{
// 增
public void save(T t);
// 改
public void update(T t);
}
/**
实现接口的同时指定泛型变量的具体数据类型
*/
public class ProductDao implements Dao<Product> {
@Override
public void save(Product product) {
System.out.println("保存产品信息...");
}
@Override
public void update(Product product) {
System.out.println("更新产品信息...");
}
}
/**
实现接口的同时指定泛型变量的具体数据类型
*/
public class StudentDao implements Dao<Student> {
@Override
public void save(Student student) {
System.out.println("保存学生信息....");
}
@Override
public void update(Student student) {
System.out.println("更新学生信息....");
}
}
/**
实现接口时不指定泛型变量的具体数据类型,将实现类定义为泛型类,
由使用者创建泛型类对象时指定泛型变量的具体数据类型。
*/
public class BaseDao<T> implements Dao<T> {
@Override
public void save(T t) {
}
@Override
public void update(T t) {
}
}
public class Demo01 {
public static void main(String[] args){
// 创建学生对象
Student stu = new Student();
// 创建Dao接口的实现类对象
StudentDao stuDao = new StudentDao();
// 保存学生
stuDao.save(stu);
// 创建产品对象
Product p = new Product();
// 创建Dao接口的实现类对象
ProductDao pdDao = new ProductDao();
// 保存产品
pdDao.save(p);
// 创建BaseDao对象
BaseDao<Student> baseDao01 = new BaseDao<>();
// 保存学生
baseDao01.save(stu);
// 创建BaseDao对象
BaseDao<Product> baseDao02 = new BaseDao<>();
baseDao02.save(p);
}
}
```
## 3.3 泛型上下限(了解)
### 3.3.1 泛型上下限引入
```java
- 需求1
- 定义一个方法可以接收任意类型的集合对象
- 集合对象只能存储Integer或者是Integer的父类数据。
- 需求2
- 定义一个方法可以接收任意类型的集合对象
- 集合对象只能存储Number或者是Number的子类数据。
```
### 3.3.2 泛型上下限格式
```java
? : 泛型通配符 代表可以匹配任意数据类型。
泛型上限:? extends Number 可以接收Number或Number的子类类型的数据
泛型下限:? super Integer 可以接收Integer或Integer的父类类型的数据。
泛型通配符注意事项
* ? 一般不会单独使用,一般会结合泛型上下限使用。
* ? 不能用来定义泛型方法,泛型类,泛型接口
? 和 泛型变量T 的区别
? 不需要定义就可以使用,T 需要先定义再使用
? 在方法体不能当成一种数据类型使用,泛型变量T可以当成一种数据类型使用。
```
### 3.3.3 示例代码
```java
public class Demo01{
public static void main(String[] args){
ArrayList<String> list01 = new ArrayList<>();
ArrayList<Integer> list02 = new ArrayList<>();
ArrayList<Object> list03 = new ArrayList<>();
ArrayList<Number> list04 = new ArrayList<>();
ArrayList<Long> list05 = new ArrayList<>();
// test01(list01); // 编译失败
test01(list02); // 编译通过
test01(list03); // 编译通过
test01(list04); // 编译通过
// test02(list01); // 编译失败
test02(list02); // 编译通过
// test02(list03); // 编译失败
test02(list04); // 编译通过
test02(list05); // 编译通过*/
}
public static void test02(ArrayList<? extends Number> list) {
}
public static void test01(ArrayList<? super Integer> list) {
}
}
```
# 小结
```java
Collection:所有单列集合的父类
Collection集合的继承体系
Collection:
List:ArrayList,LinkedList,Vector(过时)
Set:HashSet,LinkedHashSet
Collection集合常用方法
void add(E e);添加元素
void clear();清空元素
boolean remove(Object e);删除指定的元素,成功返回true,否则false
boolean isEmpty(); 判断集合是否为空,空返回true否则false
Object[] toArray();集合转数组
boolean contains(Object e);判断集合中是否包含指定元素,包含返回true,否则false。
int size();获得元素个数
迭代器概述
一个用来遍历集合的对象
该对象实现了Iterator接口
如何获得迭代器对象
* 通过调用集合对象iterator()方法获得。
Iterator接口常用方法
boolean hasNext(); 判断是否有下一个元素,有返回true,否则false
E next(); 将指针下移指向下一个元素,并返回当前指针指向位置的元素。
迭代器的好处
* 屏蔽了众多集合的内部实现,对外提供统一的遍历方式。
* 所有的单列集合都可以使用迭代器遍历。
增强for概述
* JDK1.5新特性,专门用来遍历集合和数组的,本质是:迭代器
增强for格式
* for(数据类型 遍历名:数组名或集合名){}
* 注意事项:在遍历集合过程中不能对集合元素进行增删操作,否则会出现并发修改异常。
泛型概述
* JDK1.5新特性
* 泛型可以使用在方法上,类上,接口上。
* 泛型变量可以理解为是一种数据类型的占位符,也可以理解为是一种数据类型的变量。
泛型方法概述:在定义方法时定义了泛型变量的类
泛型方法的定义格式:修饰符 <泛型变量T> 返回值类型 方法名(参数列表){}
泛型方法注意事项:泛型变量的具体数据类型是由调用者调用方法传参决定。
泛型类概述:在定义类时定义了泛型变量的类
泛型类定义格式:class 类名<泛型变量T>{ }
泛型类注意事项
泛型类上泛型变量的具体数据类型是创建对象时由使用者指定,如果没有指定,则默认是Object
静态方法不能使用类上定义的泛型变量,如果要使用,则需要将该方法定义为泛型方法。
泛型接口概述:在定义接口时定义了泛型变量的接口
泛型接口的定义格式:interface 接口名<泛型变量T>{}
泛型接口的实现方式
实现接口同时指定泛型变量的具体数据类型(不够灵活)
实现接口时不指定泛型变量的具体数据类型,将该实现类定义泛型类,由使用者创建实现类对象时指定泛型变量的 具体数据类型。
泛型上下限
? 通配符,可以匹配任意类型数据
? extends Number: 可以接收Number或Number子类数据
? super Integer: 可以接收Integer或Integer的父类数据
```