集合与泛型

129 阅读11分钟

1.集合的概述

1、什么是集合?
集合是代表一系列的数据结构,一系列的容器类型。
Java中的容器:用来装Java的对象的。
集合这些容器不装基本数据类型,如果遇到基本数据,会自动把它们装箱为包装类的对象。
​
2、集合和数组有什么区别?
数组:
    比较单一的结构,长度是不可变,(如果要对数组进行扩容等操作,必须创建新数组)。
    数组既支持基本数据类型的存储,又支持对象的存储。
    实际开发中,一般存储对象选择集合,基本数据类型才选择数组。
集合:
    类型比较丰富,长度并没有限制。
​
3、集合大致分为两大类:
(1)以Collection为根接口的系列:存储一组对象的集合
    例如:张三、李四、王五、赵六
(2)以Map为根接口的系列:存储一组键值对的集合,键值对又称为映射关系。
    键值对:(key,value)
    例如:(张三,翠花)(王五,如花)

2、Collection接口

java.util.Collection接口
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。
一些 collection 允许有重复的元素,而另一些则不允许。
一些 collection 是有序的,而另一些则是无序的。
JDK 不提供此接口的任何直接 实现:
它提供更具体的子接口(如 SetList)实现。
​

1、增删改查

(1)、增

boolean add(E e) :添加一个对象到当前集合中 boolean addAll(Collection c) :添加一组对象到当前集合中

package note;
​
import org.testng.annotations.Test;
​
import java.util.ArrayList;
import java.util.Collection;
​
/**
 * ClassName: TestCollection
 * Package: note
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-03-29 21:18
 * @Version 1.0
 */
​
​
public class TestCollection {
 @Test
 public void test1(){
   // ArrayList只是Collection的子接口List的一个实现类而已
  Collection coll = new ArrayList();
  coll.add("张三");
  coll.add("李四");
  coll.add("王五");
  System.out.println(coll); // [张三, 李四, 王五]
  }
  @Test
  public void test2(){
   // ArrayList只是Collection的子接口List的一个实现类而已
   Collection coll  = new ArrayList(); // 多态引用
​
   coll.add("张三");
   coll.add("李四");
   coll.add("王五");
​
   Collection other = new ArrayList(); // 多态引用
​
   other.add("赵六");
   other.add("钱七");
   other.add("王八");
  // coll.add(other); // [张三, 李四, 王五, [赵六, 钱七, 王八]]
​
   coll.addAll(other); // [张三, 李四, 王五, 赵六, 钱七, 王八]
   System.out.println(coll);
   }
​
​
}
​
(2)、删

void clear() :清空集合中所有的元素 boolean remove(Object o) :从当前集合中删除1个对象 boolean removeAll(Collection c) :从当前集合中删除一组对象 this集合 = this集合 - this集合 ∩ c集合 boolean retainAll(Collection c) :从当前集合中删除一组对象 this集合 = this集合 ∩ c集合 boolean removeIf(Predicate filter) :从当前集合中删除一组对象(Java8引入的) this集合 = this集合 - this集合中满足 filter过滤条件的元素 Predicate是一个接口类型,它是java.util.function包,是Java8新增。 包含抽象方法:boolean test(T t) 调用removeIf方法时,必须传入一个Predicate接口的实现类对象, 通常使用匿名内部类来实现Predicate接口。

   @Test
    public void test3() {
        Collection coll = new ArrayList();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("world");
        coll.add("world");
        coll.add("world");
        coll.remove("world"); // 只会删掉第一次出现的 ”world“
        System.out.println(coll); // [hello, java, world, world, world]
        Collection other = new ArrayList();
        other.add("hello");
        other.add("world");
        other.add("python");
        other.add("a");
        other.add("c");
      //  coll.removeAll(other); // 删除coll中与other相同的元素,返回coll中与other不同的元素
       // System.out.println(coll); // [java]
        other.removeAll(coll);
        System.out.println(other); // [python, a, c]
​
    }
    @Test
    public void test4() {
        Collection coll = new ArrayList();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("world");
        coll.add("world");
        coll.add("world");
        Collection other = new ArrayList();
        other.add("hello");
        other.add("world");
        other.add("python");
        other.add("a");
        other.add("c");
        coll.retainAll(other); // 删除不同的元素,保留相同元素
        System.out.println(coll); // [hello, world, world, world, world]
​
    }
    @Test
    public void test5() {
        Collection coll = new ArrayList(); //多态引用
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("python");
        coll.add("c");
        coll.add("world");
​
        // 删除包含o的元素
        coll.removeIf(new Predicate() {
            @Override
            public boolean test(Object o) {
                //这里需要编写的是 要从coll集合中删除的元素的判断条件
                //满足条件(即条件返回true)都要被删除
                //这里的形参o就是coll集合中的元素
                String str = (String) o;
                return str.contains("o");
            }
        });
        System.out.println(coll); // [java, c]
​
    }
(3)、改(没有提供直接替换元素的方法)
(4)、查

int size() :元素个数 boolean contains(Object o) :判断当前集合中是否包含o对象 boolean containsAll(Collection c) :判断当前集合中是否包含c集合的所有元素 判断c是否是否是当前集合的“子集” boolean isEmpty() :判断是否为空

    @Test
    public void test6() {
        Collection coll = new ArrayList();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("world");
        coll.add("world");
        coll.add("world");
        Collection other = new ArrayList();
        other.add("hello");
        other.add("world");
        other.add("python");
        other.add("a");
        other.add("c");
        //判断当前集合中是否包含java对象
        System.out.println(coll.contains("java"));  // ture
        System.out.println(other.contains("java")); // false
         // 判断当前集合中是否包含other集合的所有元素
        System.out.println(coll.contains(other));  // false
        // 查看元素个数
        System.out.println(coll.size()); // 6
         //判断是否为空
        boolean empty = coll.isEmpty();
        System.out.println(empty); //false
    }
​

2 、Collection集合的遍历

(5)、遍历

Object[] toArray() :把集合中所有元素放到一个Object[]数组中返回,然后用遍历数组的方式遍历元素。 这种方式不是特别好。 为了遍历,还要创建一个新数组。 Iterator iterator():返回一个迭代器对象,用于遍历当前集合。 java.util.Iterator接口类型。 这个接口的实现类在Collection集合的实现类的内部定义。 例如:ArrayList是Collection接口的一个实现类, 在ArrayList中有一个内部类Itr,实现了Iterator接口。

当我们调用Collection接口的iterator()时,集合的实现类会重写iterator()方法, 并返回它自己内部的Iterator接口的实现类对象。 例如:ArrayList重写的iterator()方法,就返回了Itr的对象。

无论实现类在哪里定义,都需要重写Iterator接口的抽象方法。 boolean hasNext():判断当前迭代器是否可以访问到元素,或者说,是否还有下一个元素可遍历 E next() :取出当前迭代器指向的元素,并且迭代器继续指向下一个元素

import org.testng.annotations.Test;
​
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
​
/**
 * ClassName: TestIterate
 * Package: note
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-03-30 10:52
 * @Version 1.0
 */
​
​
public class TestIterate {
    @Test
    public void test1() {
        Collection coll = new ArrayList();//多态引用
        coll.add("hello");
        coll.add("java");
        coll.add("hahahaha");
        coll.add("world");
        coll.add("hahahaha");
        coll.add("hahahaha");
        coll.add("hahahaha");
        // 把集合中所有元素放到一个Object[]数组中返回,然后用遍历数组的方式遍历元素。
        Object[] objects = coll.toArray();
        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
​
        }
​
    }
​
    @Test
    public void test2() {
        Collection coll = new ArrayList();// 多态引用
        coll.add("hello");
        coll.add("java");
        coll.add("hahahaha");
        coll.add("world");
        coll.add("hahahaha");
        coll.add("hahahaha");
        coll.add("hahahaha");
        Iterator iterator = coll.iterator(); // 多态引用
        // 左边Iterator是父接口类型
        // 右边 coll.iterator() 实际返回的是 Iterator接口的实现类对象,
        // 只不过这个实现类在ArrayList中内部类定义的。
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
​
    }
​
    @Test
    public void test3() {
        Collection coll = new ArrayList();// 多态引用
        coll.add("hello");
        coll.add("java");
        coll.add("hahahaha");
        coll.add("world");
        coll.add("hahahaha");
        coll.add("hahahaha");
        coll.add("hahahaha");
        Iterator iterator = coll.iterator(); // 多态引用
        // 左边Iterator是父接口类型
        // 右边 coll.iterator() 实际返回的是 Iterator接口的实现类对象,
        // 只不过这个实现类在ArrayList中内部类定义的。
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }
​
    }

3 、foreach循环

(6)、

JDK1.5之后,引入了一个新特性,一种新的语法糖

增加for循环,或foreach循环。 语法格式: for(元素的类型 元素名 : 数组或集合对象名){ } 元素名是我们自己命名的一个局部变量而已。

如果是数组使用foreach,那么编译器仍然处理成普通的for循环。 如果是集合使用foreach,那么编译器仍然处理成Iterator迭代器。

问:是否是所有的集合都支持用Iterator迭代器遍历呢? 或者说是否是所有的集合都支持用foreach循环遍历呢? 答案:不是。 只有实现了java.lang.Iterable接口, 因为只有实现这个接口,才能重写Iterator iterator()方法。

   @Test
    public void test1() {
        Collection coll = new ArrayList();//多态引用
        coll.add("hello");
        coll.add("java");
        coll.add("hahaha");
        coll.add("world");
        coll.add("world");
​
        //foreach的快捷键:iter或集合对象.iter
        //底层对应Iterator迭代器
        for (Object o : coll) {
            System.out.println(o);
        }
    }
    @Test
    public void test2(){
        int arr[] = {1,2,3,4,5,6,7,8,9};
        //foreach的快捷键:iter或数组对象.iter
        //底层对应普通for循环
        for (int i : arr) {
            System.out.print(i); // 123456789
        }
     }

3 、Iterator迭代器

1、 Iterator与Collection集合的关系

image-20230329153909573.png

2、 Iterator遍历元素原理

1、关系:

以ArrayList为例,在ArrayList中有一个内部类Itr,实现了Iterator接口,

重写了Iterator接口的两个重写方法: boolean hasNext() E next()

2、工作原理

任意位置按Ctrl + N:搜索java.util.ArrayList ArrayList源码中Ctrl + F12:查看ArrayList的成员列表

ArrayList是一种特殊的集合,它的底层是数组。 private class Itr implements Iterator { int cursor; //游标,迭代器下一个要返回的元素的下标,或迭代器当前指向的元素的下标 int lastRet = -1; // 迭代器上一个遍历的元素下标 //-1的意思是表示暂时不存在迭代器 上一个遍历的元素 int expectedModCount = modCount; //modCount是ArrayList集合用于记录 元素个数变化的次数 //当ArrayList添加、删除元素时,modCount都会自增1 //expectedModCount是Itr这个迭代器用于记录,迭代器准备遍历ArrayList的元素时,集合当前modCount的值 }

hasNext()中cursor的值是表示本次要遍历的元素的下标 next()中cursor会+1,表示指向下一次要遍历的元素的下标,本次要遍历的元素的下标给i lastRet=i

package note;
​
import org.testng.annotations.Test;
​
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
​
/**
 * ClassName: TestIterator
 * Package: note
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-03-30 11:24
 * @Version 1.0
 */
​
​
public class TestIterator {
    @Test
    public void test1() {
        Collection coll = new ArrayList(); // 多态引用
​
        coll.add("hello");
        coll.add("world");
        coll.add("java");
​
        Iterator iterator = coll.iterator();// 多态引用
        while (iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }
​
}
​

image-20230329154213058.png

3、 Iterator删除元素

3、

Java8之前Collection是没有removeIf方法,那么Collection的删除只有remove,removeAll,retainAll,clear等, 那就无法完成根据“条件”删除元素了。 为了实现可以根据“条件”删除元素,Iterator迭代器提供了一个remove方法,用于在Iterator遍历集合元素的过程中, 判断元素是否满足xx条件,然后再删除该元素。

结论:(一定要记住) 要从Collection集合中根据条件删除元素,首先考虑使用removeIf方法, 如果JDK是8之前的,那么在使用Iterator遍历集合并根据条件删除元素时, 切记切记要调用Iterator的remove方法,而不是Collection的remove方法。

避免:在使用Iterator或foreach遍历集合过程中,调用集合的remove、add等方法。

package note;
​
import org.testng.annotations.Test;
​
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
​
/**
 * ClassName: TestIterator
 * Package: note
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-03-30 11:24
 * @Version 1.0
 */
​
​
public class TestIterator {
    @Test
    public void test1() {
        Collection coll = new ArrayList(); // 多态引用
​
        coll.add("hello");
        coll.add("world");
        coll.add("java");
​
        Iterator iterator = coll.iterator();// 多态引用
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }
​
    @Test
    public void test2() {
        Collection coll = new ArrayList();//多态引用
        coll.add("hello");
        coll.add("java");
        coll.add("hahaha");
​
        // 删除包含”a“字母的元素
        Iterator iterator = coll.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            String str = (String)obj;
            if(str.contains("a")){
                iterator.remove();   //这里调用的是迭代器的remove方法,不是Collection集合的remove方法
​
            }
        }
        System.out.println(coll); // [hello]
​
​
    }
    @Test
    public void test3() {
        Collection coll = new ArrayList();//多态引用
        coll.add("hello");
        coll.add("java");
        coll.add("hahaha");
​
        // 删除包含”a“字母的元素
        Iterator iterator = coll.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            String str = (String)obj;
            if(str.contains("a")){
               coll.remove(str);     //调用Collection的remove方法
​
            }
        }
        System.out.println(coll); // [hello, hahaha]  漏删
​
    }
    @Test
    public void test4(){
        Collection coll = new ArrayList();//多态引用
        coll.add("hello");
        coll.add("java");
​
        //删除包含"a"字母的元素
        Iterator iterator = coll.iterator();//多态引用
        while(iterator.hasNext()){
            Object element = iterator.next();
            String str = (String) element;
            if(str.contains("a")){
                coll.remove(str);//调用Collection的remove方法
            }
        }
        //发生异常ConcurrentModificationException 并发修改异常
​
        System.out.println(coll);
​
    }
}
​

4、泛型

1、 泛型的好处

1、什么是泛型?

语法:<类型> 就是泛型 例如:,, ,

2、为什么要使用泛型?

(1)把类型的检查和确定从运行时提前到了编译时 (2)避免强制类型转换

package note;
​
import org.testng.annotations.Test;
​
import java.util.ArrayList;
import java.util.Collection;
​
/**
 * ClassName: TestGeneric
 * Package: note
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-03-30 11:39
 * @Version 1.0
 */
​
​
public class TestGeneric {
    @Test
    public void test1() {
        /*
        需求:添加5个英语单词到集合中,遍历集合,显示这些单词的长度
         */
        Collection coll = new ArrayList();
        coll.add("hello");
        coll.add("java");
        coll.add("hahaha");
        coll.add("arraylist");
        coll.add(1);
​
        for (Object o : coll) {
            System.out.println(o + "单词的长度:" + ((String) o).length());
        }
    }
​
    @Test
    public void test2() {
        /*
        需求:添加5个英语单词到集合中,遍历集合,显示这些单词的长度
         */
        Collection<String> coll = new ArrayList<String>();
        coll.add("hello");
        coll.add("java");
        coll.add("hahaha");
        coll.add("arraylist");
      //  coll.add(1);//报错,编译时提示我们1不是String
​
        for (String s : coll) {
            System.out.println(s + "单词的长度:" + s.length());
        }
    }
}
​

2 、泛型类泛型接口

3、泛型用于两个地方:

(1)类或接口名后面:把类名或接口名后面带<泛型>的类和接口称为泛型类或泛型接口 java.lang.Comparable java.util.Comparator java.util.Collection java.util.ArrayList java.lang.Iterable java.util.Iterator java.util.function.Predicate .....

(2)方法中,在方法的返回值类型前面定义<泛型> 【修饰符】 <泛型> 返回值类型 方法名(【形参列表】)throws 异常列表{

}

4、如何使用别人定义好的泛型类或泛型接口?(非常重要)

(1)使用它们声明变量和创建对象 以ArrayList为例,在整个ArrayList类中是用于表示元素的类型。 e:element

(2)继承它们或实现它们

注意: A:泛型不支持基本数据类型,必须使用引用数据类型 如果是基本数据类型,必须使用包装类。 B:JDK1.7之后, ArrayList list = new ArrayList(); 可以简化为 ArrayList list = new ArrayList<>();

public class TestIterator {
    @Test
    public void test1(){
        Collection<String> coll = new ArrayList<>();
        coll.add("java");
        coll.add("hello");
        coll.add("world");
​
        //使用Iterator迭代器遍历Collection集合
        Iterator<String> iterator = coll.iterator();
        while(iterator.hasNext()){
            String str = iterator.next();
            System.out.println(str);
        }
    }
​
    @Test
    public void test2(){
        Collection<String> coll = new ArrayList<>();
        coll.add("java");
        coll.add("hello");
        coll.add("world");
​
        //使用Iterator迭代器遍历Collection集合
        Iterator<String> iterator = coll.iterator();
        while(iterator.hasNext()){
            String str = iterator.next();
            System.out.println(str);
        }
        System.out.println("----------------------");
        //....
        System.out.println("----------------------");
        iterator = coll.iterator();//重新创建一个迭代器对象
        //跟踪实现类重写的iterator()方法,快捷键:Ctrl + Alt + B,选择实现类
        while(iterator.hasNext()){
            String str = iterator.next();
            System.out.println(str);
        }
    }
}
package note;
​
/**
 * ClassName: Student
 * Package: note
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-03-30 11:43
 * @Version 1.0
 */
​
​
​
    /*
要求:Student类实现java.lang.Comparable<T>接口
    重写int compareTo(T obj)方法
​
    <T>是代表这个比较器要比较的对象的类型。
 */
    public class Student3 implements Comparable<Student3> {
        private int id;
        private String name;
        private int score;
        private int age;
        private double weight;
​
        public Student3(int id, String name, int score, int age, double weight) {
            this.id = id;
            this.name = name;
            this.score = score;
            this.age = age;
            this.weight = weight;
        }
​
        public int getId() {
            return id;
        }
​
        public void setId(int id) {
            this.id = id;
        }
​
        public String getName() {
            return name;
        }
​
        public void setName(String name) {
            this.name = name;
        }
​
        public int getScore() {
            return score;
        }
​
        public void setScore(int score) {
            this.score = score;
        }
​
        public int getAge() {
            return age;
        }
​
        public void setAge(int age) {
            this.age = age;
        }
​
        public double getWeight() {
            return weight;
        }
​
        public void setWeight(double weight) {
            this.weight = weight;
        }
​
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + ''' +
                    ", score=" + score +
                    ", age=" + age +
                    ", weight=" + weight +
                    '}';
        }
​
        @Override
        public int compareTo(Student3 o) {
            //默认按照成绩比较大小,如果成绩相同,按照学号比较大小
            int result = Integer.compare(this.score, o.score);
            return result != 0 ? result : Integer.compare(this.id, o.id);
        }
    }
​
package note;
​
import java.util.Comparator;
​
/**
 * ClassName: StudentAgeComparator
 * Package: note
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-03-30 11:46
 * @Version 1.0
 */
​
​
/*
实现java.util.Comparator<T>接口
    int compare(T t1, T t2)
    <T>代表这个比较器要比较大小的对象的对象
​
    StudentAgeComparator用它比较两个学生对象的大小
 */
public class StudentAgeComparator implements Comparator<Student3> {
    @Override
    public int compare(Student3 o1, Student3 o2) {
        //按照年龄比较大小,如果年龄相同,按照学号大小
        int result = Integer.compare(o1.getAge(), o2.getAge());
        return result != 0 ? result : Integer.compare(o1.getId(),o2.getId());
    }
}
package note;
​
import exercise.exercise2.Employee;
import org.testng.annotations.Test;
​
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;
​
/**
 * ClassName: TestUseGenericClassInterface
 * Package: note
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-03-30 11:47
 * @Version 1.0
 */
​
​
public class TestUseGenericClassInterface {
    @Test
    public void test1(){
        /*
        使用ArrayList<E>泛型类声明一个变量,并创建它的对象。
        以ArrayList<E>为例,<E>在整个ArrayList类中是用于表示元素的类型。
        e:element
​
        案例:添加5个整数到ArrayList集合中
         */
//        ArrayList<Integer> list = new ArrayList<Integer>();
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
​
        System.out.println(list);
    }
​
    @Test
    public void test2(){
        //案例:添加5个员工对象到ArrayList集合中
        ArrayList<Employee> list = new ArrayList<>();
//        list.add("张三");//报错,"张三"是字符串类型
        list.add(new Employee(1,"张三",16000));
        list.add(new Employee(2,"李四",12000));
        list.add(new Employee(3,"王五",18000));
        list.add(new Employee(4,"赵六",19000));
        list.add(new Employee(5,"钱七",11000));
​
        //遍历集合
        for (Employee employee : list) {
            System.out.println(employee);
        }
    }
​
    @Test
    public void test3(){
        Student3[] arr = new Student3[4];
        arr[0] = new Student3(1,"张三",85,23,120);
        arr[1] = new Student3(2,"李四",96,22,140);
        arr[2] = new Student3(3,"王五",96,25,110);
        arr[3] = new Student3(4,"赵六",74,21,90);
​
        Arrays.sort(arr);//找Student类的compareTo方法比较学生对象大小
​
        for (Student3 student3 : arr) {
            System.out.println(student3);
        }
    }
​
    @Test
    public void test4(){
        Student3[] arr = new Student3[4];
        arr[0] = new Student3(1,"张三",85,23,120);
        arr[1] = new Student3(2,"李四",96,22,140);
        arr[2] = new Student3(3,"王五",96,25,110);
        arr[3] = new Student3(4,"赵六",74,21,90);
​
        Arrays.sort(arr,new StudentAgeComparator());//用定制的StudentAgeComparator比较器对象,比较两个学生的大小
​
        for (Student3 student3 : arr) {
            System.out.println(student3);
        }
    }
​
    @Test
    public void test5(){
        Student3[] arr = new Student3[4];
        arr[0] = new Student3(1,"张三",85,23,120);
        arr[1] = new Student3(2,"李四",96,22,140);
        arr[2] = new Student3(3,"王五",96,25,110);
        arr[3] = new Student3(4,"赵六",74,21,90);
​
        //按照学生的体重比较大小,如果体重相同,再按照学号比较大小
        Arrays.sort(arr, new Comparator<Student3>() {
            @Override
            public int compare(Student3 o1, Student3 o2) {
                int result = Double.compare(o1.getWeight(),o2.getWeight());
                return result != 0 ? result : Integer.compare(o1.getId(),o2.getId());
            }
        });
​
        for (Student3 student3 : arr) {
            System.out.println(student3);
        }
    }
​
    @Test
    public void test6(){
        Student3[] arr = new Student3[4];
        arr[0] = new Student3(1,"张三",85,23,120);
        arr[1] = new Student3(2,"李四",96,22,140);
        arr[2] = new Student3(3,"王五",96,25,110);
        arr[3] = new Student3(4,"赵六",74,21,90);
​
        //按照姓名的拼音顺序,如果姓名相同的,再按照学号比较
        Arrays.sort(arr, new Comparator<Student3>() {
            @Override
            public int compare(Student3 o1, Student3 o2) {
                int result = Collator.getInstance(Locale.CHINA).compare(o1.getName(),o2.getName());
                return result != 0 ? result : Integer.compare(o1.getId(),o2.getId());
            }
        });
​
        for (Student3 student3 : arr) {
            System.out.println(student3);
        }
    }
​
​
}
​

3、 自定义泛型类

5、自定义泛型类或泛型接口(了解)

【修饰符】 class 类名<泛型>{

}

注意: (1)定义泛型时,通常选择单个的大写字母,一个单个大写字母代表一个未知的类型 <K,V> <T,U,R>

案例: 定义一个学生类XueSheng,它包含姓名和成绩两个属性。 但是成绩的类型无法确定? 语文老师: 成绩:优秀、良好、及格等 英语老师: 成绩:A,B,C,D等 数学老师: 成绩:85.5,90.0等

public class XueSheng<T> {
    private String name;
    private T score;
​
    public XueSheng() {
    }
​
    public XueSheng(String name, T score) {
        this.name = name;
        this.score = score;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public T getScore() {
        return score;
    }
​
    public void setScore(T score) {
        this.score = score;
    }
​
    @Override
    public String toString() {
        return "XueSheng{" +
                "name='" + name + ''' +
                ", score=" + score +
                '}';
    }
}
​
/*
ChineseXueSheng类不再是泛型类
 */
public class ChineseXueSheng extends XueSheng<String>{
    public ChineseXueSheng() {
    }
​
    public ChineseXueSheng(String name, String score) {
        super(name, score);
    }
​
}
​
public class TestXueSheng {
    @Test
    public void test7(){
        //语文老师
        XueSheng<String> x1 = new XueSheng<>("张三","优秀");
        XueSheng<String> x2 = new XueSheng<>("李四","良好");
​
        System.out.println(x1);
        System.out.println(x2);
    }
​
    @Test
    public void test8(){
        //英语老师
        XueSheng<Character> x1 = new XueSheng<>("张三",'A');
        XueSheng<Character> x2 = new XueSheng<>("李四",'B');
​
        System.out.println(x1);
        System.out.println(x2);
    }
​
    @Test
    public void test9(){
        //数学老师
        XueSheng<Double> x1 = new XueSheng<>("张三",85D);
        XueSheng<Double> x2 = new XueSheng<>("李四",90.0);
​
        System.out.println(x1);
        System.out.println(x2);
    }
​
    @Test
    public void test10(){
        //语文老师
        ChineseXueSheng c1 = new ChineseXueSheng("张三","优秀");
        ChineseXueSheng c2 = new ChineseXueSheng("李四","良好");
​
        System.out.println(c1);
        System.out.println(c2);
    }
}