泛型的基本用法
集合中的泛型是将集合中要装的元素的数据类型给标注出来
这样可以保证集合中代码的安全,同时还可以省去我们在迭代的时候要为元素进行向下转型的麻烦
同时还能将代码运行时的错误提前到编译起,可以提高我们编写代码的效率
下面我们写一个集合,并将其遍历

//泛型主要的作用是声明集合中装的对象的数据类型
//这里实例化对象的时候,前面已经声明了泛型,在java1.7以后,后面的泛型数据类型可以省略的,后面的被称为菱形泛型
 ArrayList<String> arrayList = new ArrayList<>();
     arrayList.add("a");
     arrayList.add("b");
     arrayList.add("c");
     arrayList.add("d");
     //arrayList.add(10); 这一步因为泛型已经标注了数据类型,所以integer类型的是无法添加的
     ListIterator<String> iterator = arrayList.listIterator();//获取迭代器
    //正向遍历
    while (iterator.hasNext())
    {
        String next = iterator.next(); //因为迭代器已经标明了数据类型,省去了我们向下转型
        System.out.println(next);
    }

泛型类中,泛型就相当于将数据类型参数化,在创建类的对象的时候对泛型进行赋值数据类型,有点类似与传参数
在泛型类中有几点要注意的
1️⃣在书写泛型类的时候,泛型的形参是在创建对象的时候回被赋值实例数据类型
2️⃣在成员方法中如果调用了参数,参数的数据类型如果用的是泛型,那么我们要在方法中标注一下,在调用方法的时候,对泛型进行赋值
3️⃣在静态方法中如果传入了参数,也要标注一下在调用方法的时候,对泛型就行赋值,因为静态方法可以有类方法直接调用,不会创建对象,所以必须标注一下

public class People<T> // T就代表数据类型的形参
{
  private T t;

public People(T t) 
 {
    this.t = t;
 }
 public<M> void sayHi(M m) //传入泛型的参数,要在方法中标注一下,给予赋值
 {
    System.out.println(m);
 } 
 public static<T> void helloWorld(T t) //静态方法中,也要标注一下,给予赋值
 {
    System.out.println(t);
 }
}

集合的排序
集合的排序的方法有很多种,我们主要来看一下三种方法
我们先写一个需求,在一个集合中装入三个学生类,然后来进行排序

//Student类
public class Student {
 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;
}
public Student(String name, int age) {
    super();
    this.name = name;
    this.age = age;
};
//重写了基类的toString方法
@Override
public String toString() {
    return "Student [name=" + name + ", age=" + age + "]";
}
}

下面我们在main方法中实现这个需求:

public static void main(String[] args) 
    {
        ArrayList<Student> arrayList = new ArrayList<>();
        arrayList.add(new Student("a", 19));
        arrayList.add(new Student("c", 18));
        arrayList.add(new Student("d", 17));
        arrayList.add(new Student("b", 20));
        for (int i = 0; i < arrayList.size()-1; i++) {
            for (int j = 0; j < arrayList.size()-1-i; j++) 
            {
                Student student1 = arrayList.get(j);
                Student student2 = arrayList.get(j+1);
                if (student1.getAge()>student2.getAge()) 
                {
                    arrayList.set(j, student2);//这里运用的是list.set方法来实现根据下标来赋值
                    arrayList.set(j+1, student1);//
                    //其实上面这两部可以用到Collections中的一个方法来进行交换位置
                    //Collections.swap(arrayList,j,j+1);这是一个类方法
                }
            }
        }
    }

上面我们用的就是类似于冒泡排序的排序方法进行排序的,系统给我们提供了一个方法Collections.sort( );
系统提供的这个方法中的排序条件需要我们自己去写,这个方法是一个接口中的抽象方法,系统不知道我们怎么去排序,所以给我们提供了一个接口,让我们自己去实现这个排序条件,实现的类就是我们要排序的集合中的对象类
所以我们需要先在Student类中重写这个抽象方法,在去main方法中调用排序方法

public class Student implements Comparable<Student> { //这里注意泛型为Student类型的
 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;
}
public Student(String name, int age) {
    super();
    this.name = name;
    this.age = age;
};
//重写了基类的toString方法
@Override
public String toString() {
    return "Student [name=" + name + ", age=" + age + "]";
}
//重写了comparable接口中的排序的抽象方法
 @Override
    public int compareTo(Student o) {
        // TODO Auto-generated method stub
        //自己写排序的条件,注意系统自动进行的是升序排列,所以如果返回值大于0,就交换俩元素的位置
    return this.age - o.age;
    }
}

重写了comparable的抽象方法后,我们就可以在main方法中调用Collections中的排序方法

public static void main(String[] args) 
    {
        ArrayList<Student> arrayList = new ArrayList<>();
        arrayList.add(new Student("a", 19));
        arrayList.add(new Student("c", 18));
        arrayList.add(new Student("d", 17));
        arrayList.add(new Student("b", 20));
        Collections.sort(arrayList);//此时系统就会按照年龄进行升序排列

这里,我们可以大致分为四步:1.先到被排序的集合中的类中去实现Comparable的抽象方法 2.在抽象方法中去写明排序的条件3.写明了排序的条件后就可以去main方法中调用Collections.sort方法了
集合的嵌套
集合的嵌套 :顾名思义就是在集合中装入集合,因为集合中的元素都是对象类型的,所以是可以装集合的
下面我们看一个例子
一个学校中1个年级,每个年级有2个班,每个班有2名学生

//创建一个班级的集合,因为班级中装的是学生,所以泛型是Student类型
 ArrayList<Student> banJi1 = new ArrayList<>();
     banJi1.add(new Student("a", 15));
     banJi1.add(new Student("b", 16));
     ArrayList<Student> banJi2 = new ArrayList<>();
     banJi2.add(new Student("c", 17));
     banJi2.add(new Student("d", 18));
     //创建一个年级的集合,因为集合中装的是班级,所以泛型就是班级的类型,即ArrayList<Student>
     ArrayList<ArrayList<Student>> nianJi1 = new ArrayList<>();
     nianJi1.add(banJi1);
     nianJi1.add(banJi2);
     //创建一个学校的集合,因为学校里装的是年级,所以泛型就是年级的数型ArrayList<ArrayList<Student>>
     ArrayList<ArrayList<ArrayList<Student>>> school = new ArrayList<>();
     school.add(nianJi1);

下面我们对这个嵌套集合进行遍历

//对嵌套集合遍历,我们一般要使用foreach循环
  //前面的变量时要遍历的集合,后面是集合中的元素
     for (ArrayList<ArrayList<Student>> nianji : school) {
        for (ArrayList<Student> banji : nianji) {
            for (Student student : banji) 
            {
                System.out.println(student);
            }
        }
    }