1、Set

    • Set集合概述和特点

      • 不包含重复元素的集合
      • 没有带索引的方法,不能使用普通for循环遍历

        1. public class SetDemo {
        2. public static void main(String[] args) {
        3. //创建对象
        4. Set<String> set = new HashSet<>();
        5. set.add("王小恒");
        6. set.add("王中恒");
        7. set.add("王大恒");
        8. //遍历
        9. for(String s : set) {
        10. System.out.println(s);
        11. }
        12. Iterator<String> it = set.iterator();
        13. while (it.hasNext()) {
        14. String s = it.next();
        15. System.out.println(s);
        16. }
        17. }
        18. }
    • 哈希值

      • 哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
      • Object类中有一个方法可以获取对象的哈希值
        • public int hashCode():返回对象的哈希码值
      • 对象的哈希值的特点
        • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
        • 默认情况下,不同对象的哈希值是不同的。重写hashCode()方法,可以实现让不同对象的哈希值相同
    • HashSet集合概述和特点

      • HashSet集合特点

        • 底层数据结构是哈希表
        • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
        • 没有带索引的方法,所以不能使用普通的for循环遍历
        • 由于是Set集合,所以是不包含重复元素的集合

          1. public class HashSetDemo {
          2. public static void main(String[] args) {
          3. //创建对象
          4. HashSet<String> hashSet = new HashSet<>();
          5. hashSet.add("王小恒");
          6. hashSet.add("王中恒");
          7. hashSet.add("王大恒");
          8. //遍历
          9. for(String s : hashSet) {
          10. System.out.println(s);
          11. }
          12. System.out.println("----------");
          13. Iterator<String> it = hashSet.iterator();
          14. while(it.hasNext()) {
          15. String s = it.next();
          16. System.out.println(s);
          17. }
          18. }
          19. }

          ```java public class HashSetDemo { public static void main(String[] args) { //创建对象 HashSet hs = new HashSet<>();

          Student s1 = new Student(“王小恒”,18); Student s2 = new Student(“王中恒”,19); Student s3 = new Student(“王大恒”,20);

          Student s4 = new Student(“王小恒”,18);

          hs.add(s1); hs.add(s2); hs.add(s3); hs.add(s4);

          for(Student s : hs) {

          1. System.out.println(s.getName() + "," + s.getAge());

          } } }

    public class Student { private String name; private int age;

    1. public Student() {
    2. }
    3. public Student(String name, int age) {
    4. this.name = name;
    5. this.age = age;
    6. }
    7. public String getName() {
    8. return name;
    9. }
    10. public void setName(String name) {
    11. this.name = name;
    12. }
    13. public int getAge() {
    14. return age;
    15. }
    16. public void setAge(int age) {
    17. this.age = age;
    18. }
    19. @Override
    20. public boolean equals(Object o) {
    21. if (this == o) return true;
    22. if (o == null || getClass() != o.getClass()) return false;
    23. Student student = (Student) o;
    24. return age == student.age && Objects.equals(name, student.name);
    25. }
    26. @Override
    27. public int hashCode() {
    28. return Objects.hash(name, age);
    29. }

    }

    1. - 数据结构之哈希表
    2. - JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组。
    3. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26723396/1652001401323-8b91d736-47d6-415e-b51c-4ccaf1865b52.png#clientId=u596a5bbd-c863-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=261&id=u90dd84b2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=521&originWidth=1615&originalType=binary&ratio=1&rotation=0&showTitle=false&size=274620&status=done&style=none&taskId=uba25e145-2f69-4444-a498-08704fc0a98&title=&width=807.5)
    4. 2LinkedHashSet集合概述和特点
    5. - LinkedHashSet集合特点
    6. - 哈希表和链表实现的Set接口,具有可预测的迭代次序
    7. - 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
    8. - 由哈希表保证元素唯一,也就是说没有重复的元素
    9. 3TreeSet
    10. - TreeSet集合概述和特点
    11. - 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
    12. - TreeSet():根据其元素的自然排序进行排序
    13. - TreeSet(Comparator comparator):根据指定的比较器进行排序
    14. - 没有带索引的方法,所以不能使用普通的for循环遍历
    15. - 由于是Set集合,所以不包含重复元素的集合
    16. - 自然排序Comparable的使用
    17. - 存储学生对象并遍历,创建TreeSet集合使用**无参构造方法**
    18. - 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
    19. - 结论:
    20. - TreeSet集合存储自定义对象,无参构造方法使用的**自然排序**对元素进行排序的
    21. - 自然排序,就是**让元素所属的类实现Comparable接口**,重写compareTo(T o)方法
    22. - 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
    23. ```java
    24. /*
    25. 存储学生对象并遍历,创建集合使用无参构造方法
    26. 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
    27. */
    28. public class TreeSetDemo {
    29. public static void main(String[] args) {
    30. //创建对象、
    31. TreeSet<Student> ts = new TreeSet<>();
    32. Student s1 = new Student("wangxiaoheng",18);
    33. Student s2 = new Student("wangzhongheng",20);
    34. Student s3 = new Student("wangdaheng",19);
    35. Student s4 = new Student("aaa",19);
    36. ts.add(s1);
    37. ts.add(s2);
    38. ts.add(s3);
    39. ts.add(s4);
    40. for(Student s : ts) {
    41. System.out.println(s.getName() + "," + s.getAge());
    42. }
    43. }
    44. }
    45. public class Student implements Comparable<Student>{
    46. private String name;
    47. private int age;
    48. public Student() {
    49. }
    50. public Student(String name, int age) {
    51. this.name = name;
    52. this.age = age;
    53. }
    54. public String getName() {
    55. return name;
    56. }
    57. public void setName(String name) {
    58. this.name = name;
    59. }
    60. public int getAge() {
    61. return age;
    62. }
    63. public void setAge(int age) {
    64. this.age = age;
    65. }
    66. @Override
    67. public int compareTo(Student s) {
    68. // return 0; 代表两者相同
    69. // return 1; 代表升序
    70. // return -1; 代表降序
    71. //s1不需要跟任何比
    72. //s2要和s1比 this就代表s2 o就代表s1
    73. //如果num>0 就说明s2比s1大,升序
    74. int num = this.age - s.age;
    75. int num2 = num==0? this.name.compareTo(s.name):num;
    76. return num2;
    77. }
    78. }
    • 比较器排序Comparator的使用

      • 存储学生对象并遍历,创建TreeSet集合使用带参构造函数
      • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
      • 结论:

        • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
        • 比较器排序,就是让集合构造方法接受Comparator的实现类对象,重写compare(T 01, T 02)方法
        • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写 ```java public class TreeSetDemo { public static void main(String[] args) { //创建对象 使用内部类实现接口Comparator的实现 TreeSet ts = new TreeSet<>(new Comparator() {

          1. @Override
          2. public int compare(Student s1, Student s2) {
          3. //this.age - s.age
          4. //s1 s2
          5. int num = s1.getAge() - s2.getAge();
          6. int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
          7. return num2;
          8. }

          });

          Student s1 = new Student(“wangxiaoheng”,18); Student s2 = new Student(“wangzhongheng”,20); Student s3 = new Student(“wangdaheng”,19);

          Student s4 = new Student(“aaa”,19);

          ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); for(Student s : ts) {

          1. System.out.println(s.getName() + "," + s.getAge());

          } } }

    1. ```java
    2. public class TreeSetDemo {
    3. public static void main(String[] args) {
    4. //创建对象
    5. TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
    6. @Override
    7. public int compare(Student s1, Student s2) {
    8. int num = (s2.getMathSco() + s2.getLanSco()) - (s1.getMathSco() + s1.getLanSco());
    9. int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
    10. return num;
    11. }
    12. });
    13. Student s1 = new Student("王小恒", 50, 60);
    14. Student s2 = new Student("王中恒", 65, 65);
    15. Student s3 = new Student("王大恒", 20, 35);
    16. ts.add(s1);
    17. ts.add(s2);
    18. ts.add(s3);
    19. for (Student s : ts) {
    20. System.out.println(s.getName() + ", 总分为:" + (s.getMathSco() + s.getLanSco()));
    21. }
    22. }
    23. }
    1. public class TreeSetDemo2 {
    2. public static void main(String[] args) {
    3. //创建对象
    4. // TreeSet<Integer> ts = new TreeSet<>(); 使用TreeSet会自动进行排序
    5. //
    6. // Random r = new Random();
    7. //
    8. // while (ts.size() <= 10) {
    9. // ts.add(r.nextInt(20) + 1);
    10. // }
    11. //
    12. // System.out.println(ts);
    13. //使用HashSet不会自动排序
    14. HashSet<Integer> hs = new HashSet<>();
    15. Random r = new Random();
    16. while (hs.size()<10) {
    17. hs.add(r.nextInt(20) + 1);
    18. }
    19. System.out.println(hs);
    20. }
    21. }

    2、泛型

    • 泛型概述

      • 泛型:是JDK5中引入的特性,提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型
      • 本质是参数化类型,所操作类型被指定为一个参数
        • 参数,定义方法时有形参,然后调用方法时传递实参
      • 参数化类型,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型
      • 这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口
    • 泛型定义格式:

      • <类型>:指定一种类型的格式。此类型可以看成形参
      • <类型1,类型2>:指定多种类型的格式,多种类型之间用逗号隔开。此类型可以看成时形参
      • 将来具体调用的时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
    • 泛型的好处:

      • 把运行时期的问题提前到了编译期间
      • 避免了强制类型转换
    • 泛型类

      • 泛型类的定义格式:
        • 格式:修饰符 class 类名<类型> { }
        • 范例:public class Generic { }
          • 此处T可以随便写任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
    • 泛型方法

      • 泛型方法的定义格式:
        • 格式:修饰符<类型>返回值类型 方法名(类型 变量名) { }
        • 范例:public void show(T t) { }
    • 泛型接口

      • 泛型接口的定义格式:
        • 格式:修饰符 interface 接口名<类型>{ }
        • 范例:public interface Generic { }
    • 类型统配符

      • 为了表示各种泛型List的父类,可以使用类型通配符
        • 类型通配符:<?>
        • List<?>:表示元素类型未知的List,它的元素可以匹配任何类型
        • 这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
      • 如果说不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
        • 类型通配符上限:<?extends类型>
        • List<?extends Number>:表示的类型是Number或者字类型
      • 除了可以指定类型通配符的上限,也可以指定类型通配符的下限
        • 类型通配符下限:<?super类型>
        • List<?super Number>:它表示的类型是Number或者夫类型
    • 可变参数

      • 可变参数又称为参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的

        • 格式:修饰符 返回值类型 方法名(数据类型…变量名) { }
        • 范例:public static int sum(int…a) { }

          1. public class GenericDemo2 {
          2. public static void main(String[] args) {
          3. System.out.println(sum(1,2,3));
          4. System.out.println(sum(2,3,4,5));
          5. System.out.println(sum(3,4,5,6,7,8,9));
          6. }
          7. public static int sum(int... a) {
          8. int sum = 0;
          9. for(int i : a) {
          10. sum += i;
          11. }
          12. return sum;
          13. }
          14. }
        • 可变参数注意事项:

          • 这里的变量 a 其实是一个数组
          • 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
      • 可变参数的使用
        • Arrays工具类中有一个静态方法:
          • public static List asList(T… a):返回由指定数组支持的固定大小的列表
          • 返回的集合不能做增删操作,可以做修改操作
        • List接口中有一个静态方法:
          • public static List of(E… elements):返回包含任意数量元素的不可变列表
          • 返回的集合不能做增删改操作
        • Set接口中有一个静态方法:
          • public static Set of(E… elements):返回一个包含任意数量元素的不可变集合
          • 返回的集合不能做增删操作,没有修改的方法