Java中集合的泛型(详解)

时间:2022-09-03 16:56:22
    首先创建3个类
1个 Person类 1个Student类 1个Worker类
Person类中 写两个变量 姓名 年龄 写出构造方法
set/get方法 重写toString方法
Student类继承Person类 写出构造方法
Worker类先声明都不写
    泛型:
表示集合中 保存的数据的类型
    用集合来保存字符串 要写泛型

// 创建一个集合 保存 a b c d
//<E> 就代表 要保存的元素的类型
//后面的 尖括号 要跟前面填的 泛型保持一致
//如果前面声明了泛型 后面泛型可以省略不写
//省略不写 表示类型一致
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
//用迭代器 遍历
ListIterator<String> listIterator = list.listIterator();
while(listIterator.hasNext()){
//添加泛型之后 可以省去 强转了行的麻烦
String next = listIterator.next();
System.out.println(next);
}

写泛型的一个好处

    //创建集合 保存3个学生
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("lbw", 21));
students.add(new Student("white", 20));
students.add(new Student("wwk", 19));
//获取迭代器
ListIterator<Student> listIterator = students.listIterator();
Student student = listIterator = student.listIterator();
Student student = listIterator.next();
System.out.println(student);

//因为Worker类和Student类没有任何关系
//所以这里会出错
//但是如果不写泛型 只有在运行期才会报错
//写上泛型 可以把运行期报错 转化到 编译器就报错
Worker worker = (Worker)listIterator.next();

泛型的另一种写法

    泛型类(泛型类 声明时 尖括号中的字母 你可以随便定义)

泛型类的类型 在初始化这个类的对象时 确定
    在之前创建的Worker类中写:

public class Worker<T>{
//利用泛型写成员变量
private T t;

//利用泛型写set/get方法
public T getT() {
return t;
}

public void setT(T t) {
this.t = t;
}

//工作方法
public void work(){
System.out.println("天天搬砖 一天能搬400块");
}

//普通成员方法
public void sayHi(T t){
System.out.println(t);
}

//声明不同泛型的方法 在调用泛型方法的时候 指定泛型的类型
//<Z> 声明一个泛型 只有声明过 才能使用
public<Z> void print(Z z){
System.out.println(z);
}

//静态方法中 能不能直接使用 T
//当你调用静态方法的时候 可能还没有对象 没有对象就没指定泛型
//所以不能直接使用 T

public static<Q> void fin(Q q){
System.out.println(q);
}
}

public static void fun(){
//创建 泛型类
Worker<String> worker = new Worker<>();
//给属性赋值
worker.setT("em...");
System.out.println(worker.getT);
//调用成员方法
worker.sayHi("Emm...");
//调用方法 给定类型
worker.print("Emmm...");
//调用静态方法
Worker.fun("EmmmM...")
}

泛型接口

    //反省接口
interface InterA<Y>{
void fun(Y y);
}

//实现类
class InterAImpl implements InterA<String>{
@Override
public void fun(String y){
System.out.println(y);
}
}
    以上内容只需要看懂就行

? extends E(向下限定)

? super E(向上限定)

    addAll中的 
? extends E(向下限定)
? 是子类 E 是父类
? 只能是 E类 的 子类
    addAll中的
? super E(向上限定)
? 是父类 E 是 子类 ? 只能是 E类的 父类
    /*
* 创建一个保存人的 集合 存2人
* 创建一个保存学生的集合 存2人
*/

public static void fun1() {
ArrayList<Person> pList = new ArrayList<>();
pList.add(new Person("ygs", 21));
pList.add(new Person("sxm", 20));

ArrayList<Student> sList = new ArrayList<>();
sList.add(new Student("hzn", 19));
sList.add(new Student("sxd", 21));
// 学生的集合 全部添加到 人的集合中
// ? extends Person 只能填Person的子类
pList.addAll(sList);
//sList.addAll(pList); 会报错
System.out.println(pList);
}

Arrays方法中的 数组转集合

    int[] array = {1, 2, 3, 4, 5};
// 没有经过自动装箱的数组
// 在转化成集合的时候
// 相当于 把数组当做集合中的一个元素
// 转为了集合
List<int[]> asList = Arrays.asList(array);
//集合长度为1
System.out.println(asList);

// 打印出来的是一个地址
// 因为传进数组里的元素是基本数据类型
// 没有经过自动装箱
// 而集合中储存的是 引用数据类型
// 所以打印出来的是地址


//自动装箱为 Integer类型
Integer[] array2 = {1, 2 ,3 , 4, 5};
List<Integer> asList2 = Array.asList(array2);
System.out.println(asList2);
//集合 asList2 的长度为 5

String[] array3 = {"nihao","fanchilema"}
//数组转集合
List<String> asList3 = Arrays.asList(array3);
System.out.println(asList3);
// 使用 asLis数组转集合 得到一个集合
// 注意: 这个集合不允许 进行添加或删除的操作
// 不能进行添加或删除的操作 那么这么转化有什么意义?
//虽然不能进行删除和添加 但是可以调用集合其他方法

//查看是否包含
boolean isContains = asList3.contain("nihao");
System.out.println(isContains);

一个小知识

    public static void fun(int ... num){
//遍历
for(int i = 0; i < num.length; i++){
System.out.println(num[i]);
}
}

//通过遍历发现 num 有长度
//int ... num 相当于传入的参数 是个数组

//如果在 int ... num 之前 加其他参数
//例如: int a, int ... num
//发现也是可以的
//但是加在int ... num 之后就会出错
//所以int ... num 只能是方法参数的最后一个
// int ... num 可以接收多个参数

public static void main(String[] args){
//调用一 直接传入数组
int[] array = {1, 2, 3, 4, 5};
fun(array);

//调用二 传入多个数
fun(1, 3, 5, 7, 9);
}

集合中的删除方式

    注:这个方法需要掌握

不使用迭代器

    public static void fun1() {
// 创建集合 保存 a b c d e
//
ArrayList<String> aList = new ArrayList<>();
aList.add("a");
aList.add("b");
aList.add("b");
aList.add("c");
aList.add("d");
aList.add("e");
// 不使用迭代器 遍历
// 如果集合中有 b 就把 b 删除
for(int i = 0; i < aList.size(); i++){
if(aList.get(i).equals("b")){
//先当参数传进去 再进行自减
aList.remove(i--);

//这里的i-- 是因为当你删除一个b的时候
//你的指针会只在 1 这个位置
//但是这个时候第一个b被删除了
//后面的值都补上来
//第二个b的角标就变成1
//但是循环会++
//所以指针就会指向角标为2的地方
//也就是c
//这时重复的这个b就不会被删除
//所以需要-- 将指针向前一步
}
}
}

使用迭代器删除

    public static void fun2() {
//迭代器删除
// 创建集合 保存 a b c d e
ArrayList<String> aList = new ArrayList<>();
aList.add("a");
aList.add("b");
aList.add("b");
aList.add("c");
aList.add("d");
aList.add("e");
// 获取迭代器
ListIterator<String> listIterator = aList.listIterator();
while(listIterator.hasNext()){
String next = listIterator.next();
if(next.equals("b")){
//使用迭代器删除
listIterator.remove();
}
}
System.out.println(aList);
}
快速遍历
    //fun1();
//fun2();
// 创建集合 保存 a b c d e
ArrayList<String> aList = new ArrayList<>();
aList.add("a");
aList.add("b");
aList.add("b");
aList.add("c");
aList.add("d");
aList.add("e");
// 增强for循环便令 底层是使用迭代器遍历的
// 增强for循环 只能 用来 遍历 也叫 快速遍历
// 双层遍历的时候 使用的比较多
for (String string : aList) {
System.out.println(string);
}
}
Day.18