前言

b站java课程学习笔记整理。

b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程

220. 集合体系结构

集合类的体系结构

221. collection集合的概述和使用

collect是单列集合的顶层接口,他表示一组对象,这些对象也成为Collection元素。

JDK不提供此接口的任何直接实现,它提供更具体的子接口(如SetList)实现。

创建Collection集合的对象

  • 多态的形式
  • 具体的实现类ArrayList
package Collection演示;

import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<String>();

        // 添加元素(和ArrayList方法一样)
        c.add("hello");
        c.add("world");
        // 重写了toString方法
        System.out.println(c);
    }
}

222.Collection集合的常见用法

方法名 说明
boolean add(E e) 添加元素
boolean remove(Object o) 从集合中移除指定的元素
void clear() 清空集合中的元素
boolean contains(Object o) 判断集合中是否存在指定元素
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中元素的个数
package Collection演示;

import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo2 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<String>();
        System.out.println(c.add("Hello")); //输出的是是否添加成功,调用add方法永远返回的都是true。
        c.add("World");
        c.add("World");

        System.out.println(c);

        c.remove("World");
        c.remove("asdasd"); //返回的是false,没有这个字符串。
        System.out.println(c);  //一次只能去除一个。

        boolean flag = c.contains("Hello");
        System.out.println(flag);

        c.clear();
        System.out.println(c);

        System.out.println(c.isEmpty());


    }
}

223.Collection集合的遍历

Iterator: 迭代器,集合的专用遍历方式。他是依赖于集合的存在。(”一个一个找元素”器)

迭代器的方法:

  • E next(): 返回迭代中的下一个元素。
  • boolean hasNext(): 如果迭代具有更多元素,则返回true
package Collection演示;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo3 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<String>();
        System.out.println(c.add("Hello")); //输出的是是否添加成功,调用add方法永远返回的都是true。
        c.add("World");
        c.add("java");

        Iterator<String> it = c.iterator();

/*        System.out.println(it.next());
        System.out.println(it.next());
        System.out.println(it.next());*/

        // 异常:System.out.println(it.next());
        while(it.hasNext()){
            String s =it.next();
            System.out.println(s);
        }


    }
}

224.集合使用步骤图解

说白了就是指针。

Collection图解

225.collection集合存储学生对象并遍历

和之前那个Arraylist项目差不多,不同的是collection集合可以使用迭代器遍历。

package Collection集合存储学生对象;

import 存储学生对象并遍历.Student;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class test {
    public static void main(String[] args) {
        Student s1 = new Student("林青霞", "30");
        Student s2 = new Student("张曼玉", "14");
        Student s3 = new Student("王祖贤", "18");

        Collection<Student> c = new ArrayList<>();
        c.add(s1);
        c.add(s2);
        c.add(s3);

        Iterator<Student> it = c.iterator();

        while (it.hasNext()) {
            Student s = it.next();
            System.out.println(s.getName() + s.getAge());
        }


    }
}

226.list集合

list继承自collection集合,collection集合中的功能都能用。

list是有序集合,并且它允许重复的元素。

package list集合;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class listDemo1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("hello");
        list.add("world");
        list.add("world");

        System.out.println(list);

        Iterator<String> it = list.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
        }

    }
}

227.list集合特有功能

这些功能,他的父类collection没有,但是子类ArrayList有。

这些方法是:

方法 作用
void add(int index, E element) 在指定位置插入元素
E remove(int index) 删除指定索引处的元素
E set(int index, E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素
package list集合;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class listDemo1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("hello");
        list.add("world");
        list.add("world");

        list.add(2, "nihao");
        System.out.println(list);

        list.remove(3);
        System.out.println(list);

        System.out.println(list.set(1, "JaveA"));
        System.out.println(list);

        System.out.println(list.get(1));

        // 另一种方法遍历
        int j = list.size();
        for (int i = 0; i < j; i++) {
            System.out.println(list.get(i));
        }

    }
}

228.list集合存储学生对象并遍历

package list存储学生对象;

import 存储学生对象并遍历.Student;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListDemo {
    public static void main(String[] args) {
        Student s1 = new Student("林青霞", "30");
        Student s2 = new Student("风清扬", "29");
        Student s3 = new Student("左冷禅", "28");

        List<Student> l = new ArrayList<Student>();
        l.add(s1);
        l.add(s2);
        l.add(s3);

        // 遍历可以用collection的迭代器,也可以用for循环和.get结合
        Iterator<Student> iterator = l.iterator();
        while (iterator.hasNext()) {
            Student s = iterator.next();
            System.out.println(s.getName() + "," + s.getAge());
        }
        System.out.println("--------------");

        for (int i = 0; i < l.size(); i++) {
            System.out.println(l.get(i).getName() + "," + l.get(i).getAge());
        }
    }
}

229.并发修改异常

说人话总结: 使用迭代器进行迭代的时候不能增加和减少元素的个数。

比如,老板叫迭代器去搬十块砖。迭代器接到命令就去干活了。等到搬到第八块砖的时候迭代器接到老板电话,说改要求需要他去搬十一块砖了。

这和迭代器一开始签的搬十块砖的合同不一样,违约了。迭代器一生气不干了!

package list集合;

import 存储学生对象并遍历.Student;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class listDemo1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("hello");
        list.add("world");
        list.add("java");

        // 产生并发修改异常
        /*Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String s = iterator.next();
            if(s.equals("world")){
                list.add("javaee");
                
            }

        }*/
        // 用for循环解决问题。
        for(int i=0; i<list.size();i++){
            String s =list.get(i);
            if(s.equals("world")){
                list.add("javaee");
            }
        }
        System.out.println(list);

    }
}

230.列表迭代器

ListIterator:列表迭代器

  • 通过List集合的listIterator()方法得到,所以说它是list集合特有的迭代器。
  • 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置。
package list集合;

import 存储学生对象并遍历.Student;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class listDemo1 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("hello");
        list.add("world");
        list.add("java");

        // 产生并发修改异常
        /*Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String s = iterator.next();
            if(s.equals("world")){
                list.add("javaee");
                // 通过添加break也可以解决错误
            }

        }*/
        ListIterator<String> lit = list.listIterator();
        while(lit.hasNext()){
            String s = lit.next();
            if(s.equals("world")) {
                lit.add("javaee");
            }
        }
        System.out.println(list);
    }
}

ListIteratorIterator功能大致相同,都有hasnextnext

但是ListIteratoradd功能不会有并发修改异常。

231.增强for循环

增强for:简化ListCollection集合的遍历

  • 实现Iterable接口的类允许其对象成为增强型for语句的目标
  • 它是JDK5之后出现的。其内部原理是一个Iterator迭代器。
package 增强for;

import java.util.ArrayList;
import java.util.List;

public class ForDemo {
    public static void main(String[] args) {
        int[] arr = {1, 3, 6, 7, 9};
        // 对于arr数组里面的每一个int类型的个体i
        for (int i : arr) {
            System.out.println(i);
        }
        // 对于arr2数组里面的每一个String类型的个体s
        String[] arr2 = {"hello", "world", "java"};
        for(String s : arr2){
            System.out.println(s);
        }

        List<String> list = new ArrayList<String>();
        list.add("hello");
        list.add("world");
        list.add("java");

/*        for(String s: list){
            System.out.println(s);
        }*/


        for(String s: list){
            if(s.equals("world")){
                list.add("javaee");

            }
        }
        System.out.println(list);
    }
}
 

很奇怪,老师说for增强循环内核是Iterator迭代器,可是我并没有抛出并发错误……

后来才发现原来我的list中是没有world的,那if语句就不执行,就不报错了。

232.list集合存储学生对象用三种方式遍历

三种方式分别为:Iteratorfor增强for

package list学生对象三种遍历;

import 存储学生对象并遍历.Student;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class listDemo {
    public static void main(String[] args) {
        Student s1 = new Student("林青霞", "21");
        Student s2 = new Student("张曼玉", "19");

        List<Student> l = new ArrayList<Student>();

        l.add(s1);
        l.add(s2);

        // 迭代器
        Iterator<Student> it = l.iterator();
        while (it.hasNext()) {
            Student s = it.next();
            System.out.println(s.getName() + "," + s.getAge());
        }

        // 普通for
        for (int i = 0; i < l.size(); i++) {
            Student s = l.get(i);
            System.out.println(s.getName() + "," + s.getAge());
        }

        // 增强for
        for (Student s : l){
            System.out.println(s.getName() + "," + s.getAge());
        }
    }

}

一般来说就用for就够了。iterator不咋常用。

233.数据结构之栈和队列

栈:

一端开口,先进后出。

队列:

  1. 数据从后端进入队列模型的过程称为:入队列
  2. 数据从前端离开队列模型的过程称为:出队列

队列两端开口,先进先出。

234.数据结构之数组和链表

数组:查询快,增删慢的模型。

  • 查询数据通过索引定位,查询任意数据耗时相同,查询效率高。
  • 删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低。
  • 添加数据时,添加位置后的每个数据后移,再添加元素,添加效率极低。

链表:节点的存储位置(地址)

链表的一个节点包含了这个节点的地址、数据、下一个节点的地址。

  • 链表是一种增删快的模型(对比数组)
  • 链表是一种查询慢的模型(对比数组)。因为查询数据D是否存在必须从头节点开始查。

235.list集合的子类特点

ArrayListLinkedList,底层数据结构一个是数组一个是列表。 用法和List一样的。(因为是继承)

练习:使用ArrayListLinkedList使用三种方法存储字符串并遍历。

package 数组与链表;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

public class test {
    public static void main(String[] args) {
        // 创建Arraylist
        ArrayList<String> al = new ArrayList<>();
        al.add("林青霞");
        al.add("张曼玉");
        al.add("王祖贤");
        System.out.println(al);


        // 三种方法遍历
        // 迭代器

        Iterator<String> it = al.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }

        //普通for循环

        for(int i =0; i < al.size(); i++){
            String s = al.get(i);
            System.out.println(s);
        }

        // 增强for循环
        for(String s : al){
            System.out.println(s);
        }

        // 创建链表
        LinkedList<String> ll = new LinkedList<>();
        ll.add("学雷锋");
        ll.add("做好事");
        ll.add("不留名");

        //迭代器
        Iterator<String> itr = ll.iterator();
        while(itr.hasNext()){
            String s = itr.next();
            System.out.println(s);
        }

        //普通for
        for(int i =0; i < ll.size(); i++){
            String s = ll.get(i);
            System.out.println(s);
        }

        // 增强for循环
        for(String s : ll){
            System.out.println(s);
        }



    }
}

236.ArrayList存储学生对象三种遍历

太简单了。

package 数组与链表;

import 存储学生对象并遍历.Student;

public class Rewrite extends Student {

    public Rewrite() {
    }

    public Rewrite(String name, String age) {
        super(name, age);
    }

    @Override
    public String toString() {
        return "姓名是" + getName() + "年龄是"+ getAge();
    }
}

package 数组与链表;

import 存储学生对象并遍历.Student;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

public class test {
    public static void main(String[] args) {
        Rewrite s1 = new Rewrite("林青霞","20");
        Rewrite s2 = new Rewrite("张曼玉","19");
        Rewrite s3 = new Rewrite("郭子维","17");

        // 创建Arraylist

        ArrayList<Rewrite> al = new ArrayList<>();
        al.add(s1);
        al.add(s2);
        al.add(s3);
        System.out.println(al);
        System.out.println("----------------------");


        // 三种方法遍历
        // 迭代器

        Iterator<Rewrite> it = al.iterator();
        while(it.hasNext()){
            Rewrite s = it.next();
            System.out.println(s);
        }
        System.out.println("----------------------");
        //普通for循环

        for(int i =0; i < al.size(); i++){
            Rewrite s = al.get(i);
            System.out.println(s);
        }
        System.out.println("----------------------");
        // 增强for循环
        for(Student s : al){
            System.out.println(s);
        }



    }
}

为了输出方便,重写了toString方法。

237.LinkedList的特有方法

方法名 说明
public void addFirst(E e) 在该列表的开头插入指定的元素
public void addLast(E e) 在该列表的结尾插入指定的元素
public E getFirst() 返回此列表中的第一个元素
public E getFirst() 返回此列表中的最后一个元素
public E removeFirst() 从此列表中删除并返回第一个元素
public E removeLast() 从此列表中删除并返回最后一个元素
package 链表集合特有方法;

import java.util.LinkedList;

public class LinkedListDemo {
    public static void main(String[] args) {
        // 创建链表

        LinkedList<String> ll = new LinkedList<>();

        ll.add("林青霞");
        ll.add("张曼玉");
        ll.add("王祖贤");

        // 方法1
        ll.addFirst("开头");
        System.out.println("方法1"+ll);
        // 方法2
        ll.addLast("结尾");
        System.out.println("方法2"+ll);
        // 方法3
        System.out.println("方法3"+ll.getFirst());
        // 方法4
        System.out.println("方法4"+ll.getLast());
        // 方法5
        System.out.println("方法5"+ll.removeFirst());
        System.out.println(ll);
        // 方法6
        System.out.println("方法6"+ll.removeLast());
        System.out.println(ll);
    }
}

238.Set集合概述和特点

set集合特点不包含重复的元素,没有带索引的方法,不可以使用for循环遍历。

HashSet对集合的迭代顺序不做任何的保证。

使用SetSet的子类,拓展名要装箱!而String默认已经装箱。

import java.util.HashSet;
import java.util.Set;

public class SetDemo {
    public static void main(String[] args) {
        Set<String> s = new HashSet<>();

        s.add("林青霞");
        s.add("风清扬");
        s.add("李冰冰");
        s.add("李冰冰");

        //两种方式遍历,迭代器或者增强for
        for(String i: s){
            System.out.println(i); // 不保证输出的顺序,且不能包含重复元素
        }

    }
}

239.哈希值

哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值。

Object类中有一个方法可以获得对象的哈希值。

  • public int hashCode(): 返回对象的哈希码值
package 获取哈希值;

import 存储学生对象并遍历.Student;

public class HashDemo {
    public static void main(String[] args) {
        Student s1 = new Student("林青霞", "12");

        // 同一个对象多次调用哈希值,返回的数值相同。
        System.out.println(s1.hashCode()); //2129789493
        System.out.println(s1.hashCode()); //2129789493

        Student s2 = new Student("林青霞", "12");
        // 默认情况下不同对象的哈希值是不相同的。如果在Student类中重写hashcode方法,可以实现不同对象的哈希值相同。
        System.out.println(s2.hashCode()); //668386784

        System.out.println("hello".hashCode()); //99162322
        System.out.println("world".hashCode()); //113318802
        System.out.println("world".hashCode()); //113318802

        System.out.println("重地".hashCode()); // 1179395
        System.out.println("通话".hashCode()); // 1179395 
        // 为什么重地和通话哈希码相同?因为哈希值是有范围的,汉字是无限的。没办法超出编制了,只能发重复哈希码
        System.out.println("我的".hashCode());
    }


}

为什么“重地”和“通话”哈希码相同?因为哈希值是有范围的,汉字是无限的。没办法超出编制了,只能发重复哈希码。

相同的对象哈希码相同。

240.哈希set集合的概述和特点

  1. 底层数据结构是哈希表。
  2. 对集合迭代顺序不做保证
  3. 没有带索引的方法,不能用普通for循环
  4. 不包括重复元素

补充:个人认为HashSetSet相比优势在于可以自定义什么是“重复数据”。 而且Set也得用HashSet的多态形式实现。属于是一个特例?

package Hashset;

import java.util.HashSet;

public class HashSetDemo {
    public static void main(String[] args) {
        HashSet<String> hs = new HashSet<>();
        hs.add("林青霞");
        hs.add("风清扬");
        hs.add("王冰冰");
        hs.add("王冰冰");
        System.out.println(hs);

        for(String s : hs){
            System.out.println(s);
        }

    }
}

241.HashSet集合保证元素唯一性的源码分析

HashSet集合保证元素的一致性 没看懂 后面再说吧

242.常见数据结构之哈希表

哈希表默认长度为16。

拉链法解决哈希冲突:

  1. 先哈希值对16取余,算出地址(即需要存储在哪一个格子中)
  2. 再判断该位置是否已经有元素了。
    • 该位置没有元素,那这个元素就是第一个元素
    • 该位置有元素了,比较哈希值。如果哈希值不相同,那以链表的形式添加这个元素。
    • 哈希值也相同,调用qual()方法比较元素内容。元素内容不相同,添加这个元素
    • 元素内容相同,不添加

哈希表

解决了上节的疑惑!

243.HashSet集合存储学生对象并遍历

和之前的项目相同。但是如果学生对象的成员变量相同,那就认为是同一个对象。

思路:

  1. 定义学生类。
  2. 创建HashSet集合对象
  3. 创建学生对象
  4. 把学生添加到集合
  5. 遍历集合(增强for)
  6. 在学生类中重写两个方法hashCode()equals()自动生成即可。
package 存储学生对象并遍历;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public Student(){
    };

    public Student(String name, String age){
        this.name = name;
        this.age = age;
    };


    public void show(){
        System.out.println("名字是"+name+",年龄是"+age);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (name != null ? !name.equals(student.name) : student.name != null) return false;
        return age != null ? age.equals(student.age) : student.age == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (age != null ? age.hashCode() : 0);
        return result;
    }
}

package Hashset;

import 存储学生对象并遍历.Student;

import java.util.HashSet;

public class StudentDemo {
    public static void main(String[] args) {
        Student s1 = new Student("林青霞", "张曼玉");
        Student s2 = new Student("黄祯", "23");
        Student s3 = new Student("我爱罗", "99");

        Student s4 = new Student("黄祯", "23");

        HashSet<Student> hs = new HashSet<>();

        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        hs.add(s4);
        for (Student s : hs) {
            System.out.println(s.getName() + "," + s.getAge());
        }

    }
}

244.LinkedHashSet集合概述和特点

  • 哈希表和链表实现的Set接口,具有可预测的迭代次序。
  • 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的。
import java.util.LinkedHashSet;
public class LinkedHashSetDemo {
    public static void main(String[] args) {

        LinkedHashSet<String> lhs = new LinkedHashSet<>();
        lhs.add("hello");
        lhs.add("world");
        lhs.add("java");

        for(String s:lhs){
            System.out.println(s);
        }
        //输出:hello
            //  world
        //   java

        lhs.add("java");
        for(String s:lhs){
            System.out.println(s);
        }
    }
}

245.TreeSet集合概述和特点

  1. 元素有序,不是存储和取出的排序,而是根据构造方法排序。
    • TreeSet(): 根据其元素的自然排序进行排序
    • TreeSet(Comparator comparator):根据指定的比较器进行排序
  2. 没有带索引的方法,所以不能使用普通for循环遍历
package TreeSet;

import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<Integer>();

        ts.add(10);
        ts.add(20);
        ts.add(50);
        ts.add(40);
        ts.add(30);
        ts.add(30);

        System.out.println(ts);
        for (Integer i : ts){
            System.out.println(i);
        }
    }
}

246.Comparable的使用

首先,要想对一个TreeSet的内部元素排序,默认的包装类是可以的。但是如果这个包装类是自己定义的类(比如Student),就必须让这个自定义类实现Comparable 接口。

实现接口后,通过重写CompareTo(T o)方法实现比较。注意实现接口的时候要注明接口的泛型<NewStudent>

package TreeSet;

import 存储学生对象并遍历.Student;

public class NewStudent extends Student implements Comparable<NewStudent>{
    public NewStudent() {
    }

    public NewStudent(String name, String age) {
        super(name, age);
    }

    // public String name = getName();


    @Override
    public int compareTo(NewStudent s) {
        int thisAge = Integer.parseInt(this.getAge());
        int Age = Integer.parseInt(s.getAge());  //比较的一个是s的,一个是this的。
        int num1 = thisAge-Age;
        int num2 = num1 == 0? this.getName().compareTo(s.getName()):num1;
        return num2;
    }

    @Override
    public String toString() {
        return getName()+","+getAge();
    }
}

package TreeSet;

import java.util.TreeSet;

public class ComparableDemo {
    public static void main(String[] args) {
        NewStudent s1 = new NewStudent("Qingxia Lin","21");
        NewStudent s2 = new NewStudent("Qingyang Feng","18");
        NewStudent s3 = new NewStudent("Jiangeng Sun","19");
        NewStudent s4 = new NewStudent("Wong Zing", "19");



        TreeSet<NewStudent> ts = new TreeSet<NewStudent>();

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

        for(NewStudent ns: ts){
            System.out.println(ns);
        }


    }
}

247.比较器Comparator的使用

Comparable差不多作用。这个是在测试类直接用内部类的形式使用。

package TreeSet;

import 存储学生对象并遍历.Student;

import java.util.Comparator;
import java.util.TreeSet;

public class ComparatorDemo {
    public static void main(String[] args) {
        TreeSet<NewStudent> ts = new TreeSet<NewStudent>(new Comparator<NewStudent>() {
            @Override
            public int compare(NewStudent s1, NewStudent s2) {
                int s1Age = Integer.parseInt(s1.getAge());
                int s2Age = Integer.parseInt(s2.getAge());
                int num1 = s1Age - s2Age;
                int num2 = num1 == 0? s1.getName().compareTo(s2.getName()):num1;
                return num2;
            }
        });


        NewStudent s1 = new NewStudent("Qingxia Lin","21");
        NewStudent s2 = new NewStudent("Qingyang Feng","18");
        NewStudent s3 = new NewStudent("Jiangeng Sun","19");
        NewStudent s4 = new NewStudent("Wong Zing", "19");
        NewStudent s5 = new NewStudent("Wong Zing", "19");



        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        for(NewStudent ns: ts){
            System.out.println(ns);
        }
    }
}

小结: 比较和比较器用来比较包装好的对象比较好用。基本类型比较(比如int数组中元素排序)还是用sort排好一点。

248.成绩排序

对小学生(名字语文成绩数学成绩)进行排序。需求:总分由高到低。

package 成绩排序;

public class Student implements Comparable<Student> {
    // 成员变量

    private String name;
    private int ChineseScore;
    private int MathScore;

    public Student(String name, int chineseScore, int mathScore) {
        this.name = name;
        ChineseScore = chineseScore;
        MathScore = mathScore;
    }

    public Student() {
    }

    ;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getChineseScore() {
        return ChineseScore;
    }

    public void setChineseScore(int chineseScore) {
        ChineseScore = chineseScore;
    }

    public int getMathScore() {
        return MathScore;
    }

    public void setMathScore(int mathScore) {
        MathScore = mathScore;
    }

    @Override
    public int compareTo(Student s) {

        int STotal = s.ChineseScore + s.MathScore;
        int ThisTotal = this.ChineseScore + this.MathScore;
        int num = STotal - ThisTotal;
        int num2 = num == 0 ? this.name.compareTo(s.name) : num;
        return num2;
    }

    @Override
    public String toString() {
        return "姓名" + getName() + ", 语文成绩为" + getChineseScore() + ", 数学成绩为" + getMathScore() + ", 总分为" + (getChineseScore() + getMathScore());

    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        return name != null ? name.hashCode() : 0;
    }
}
package 成绩排序;

import java.util.HashSet;
import java.util.TreeSet;

public class ScoreSort {
    public static void main(String[] args) {
        Student s1 = new Student("Jiangeng Sun", 112,150);
        Student s2 = new Student("Wong Zing", 150,130);
        Student s3 = new Student("Weihan Li", 150,150);
        Student s4 = new Student("Jitong Shi", 130,150);
        Student s5 = new Student("Jitong Shi", 130,150);
        Student s6 = new Student("Jitong Shi", 129,140);


        TreeSet<Student> treeSet = new TreeSet<>();
        // 如果重复添加同名数据,可以用hashSet过滤。
        // 过滤前
        HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(s1);
        hashSet.add(s2);
        hashSet.add(s3);
        hashSet.add(s4);
        hashSet.add(s5);
        hashSet.add(s6);
        for(Student s: hashSet){
            System.out.println(s);
            treeSet.add(s);
        }
        System.out.println("-------------------");
        // 过滤后再用treeSet排序

        for(Student s: treeSet){
            System.out.println(s);
        }


    }
}

总结:为了输出好看,重写了toString方法。为了过滤掉重复添加一个人元素,重写了hashCode方法和equals()方法,并且使用HashSet过滤了一遍。

249. 不重复的随机数

需求:输出十个不同的1-20的随机数。

用的Math.random写的,老师用的Random r创建对象。核心思想不变。

也可以用TreeSet生成,生成后会排序。

package 十个随机数;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class TenRandom {
    public static void main(String[] args) {
        boolean flag = true;
        Set<Integer> set = new HashSet<Integer>();
        while (flag) {
            int num = (int) (Math.random() * 20 + 1);
            set.add(num);
            int size = set.size();
            if (size == 10) {
                flag = false;
            }

        }
        System.out.println(set);
    }
}

250. 泛型概述和好处

这个就是泛型<>

泛型的好处:

  1. 把运行时的error提前到了编译期间。
  2. 避免了强制类型转换。

251. 泛型类

用处:想用一个方法接收很多类型的变量。

package Generic;

public class Student<T> {
    private T t;

    public T getT() {
        return t;
    }

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

package Generic;

public class test {
    public static void main(String[] args) {
        Student<String> s = new Student<String>();

        s.setT("名字");

        Student<Integer> s1 = new Student<Integer>();

        s1.setT(21);

        System.out.println(s.getT()+","+s1.getT());


    }
}

252. 泛型方法

可以在创建对象的时候不定义泛型,但是在调用实际方法的时候定义泛型。

package Generic;

public class GenericStudent{

    public <T> void show(T t){
        System.out.println(t);
    }

}

package Generic;

public class test {
    public static void main(String[] args) {
        GenericStudent genericStudent = new GenericStudent();
        genericStudent.show("String类型");
        genericStudent.show(20);
        genericStudent.show(20.12);
        genericStudent.show(false);


    }
}

253. 泛型接口

定义格式:public interface Generic <T>{}

package 泛型接口;

public interface Generic<T> {
    public void show(T t);
}

package 泛型接口;

public class GenericImplement<T> implements Generic<T>{
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}

package 泛型接口;

public class test {
    public static void main(String[] args) {
        GenericImplement<String> GI = new GenericImplement<String>();

        GI.show("林青霞");

        GenericImplement<Object> GI2 = new GenericImplement<Object>();

        GI2.show("林青霞");
        GI2.show(30);

    }
}

254. 类型通配符

类型的家族: Object \(\rightarrow\) Number \(\rightarrow\) Integer

<? extends Number> 决定了上限, <? super Number>决定了下限。

package 类型通配符;

import java.util.ArrayList;
import java.util.List;

public class GenericDemo {
    public static void main(String[] args) {
        List<?> l = new ArrayList<Object>();
        List<?> l2 = new ArrayList<Number>();
        List<?> l3 = new ArrayList<Integer>();


        // List<? extends Number> l4 = new ArrayList<Object>();
        List<? extends Number> l5 = new ArrayList<Number>();
        List<? extends Number> l6 = new ArrayList<Integer>();

        List<? super Number> l7 = new ArrayList<Object>();
        List<? super Number> l8 = new ArrayList<Number>();
        // List<? super Number> l9 = new ArrayList<Integer>();

        // l.add("2");

    }
}


255. 可变参数

方法中的参数的数量可变。本质上是把参数们分封装到一个数组中。

格式:public static int sun(int...a){};

package 可变参数;

public class ArgsDemo01 {
    public static void main(String[] args) {
        System.out.println(sum(10,20));
        System.out.println(sum(10,20,30));
        System.out.println(sum(10,20,30,40));
        System.out.println(sum(10,20,30,40,50));

        System.out.println(sum(10));
        System.out.println(sum());

    }

    public static int sum(int... a) {
        int sum = 0;
        for (int num : a) {
            sum += num;
        }
        return sum;
    }
}

注意:一个方法如果有多个参数(单一的参数和可变参数并存),可变参数要放到后面,用逗号隔开。

256. 可变参数的使用

  1. Arrays工具类中有一个静态方法: asList(T... a ): 返回由指定数组支持的固定大小的列表。
  2. List接口中有一个静态方法:of(E... elements):返回包含任意数量元素的不可变列表。
  3. Set接口中有一个静态方法:of(E... elements):返回一个包含任意数量元素的不可变集合。

注意:

正常用list集合的话是创建list对象(使用ArrayList),然后add()。使用asList(可变参数)生成的列表,无法增删!但是可以修改。

通过List.of创建的列表,无法增删修改

Set在赋值时元素不能重复,不能增删操作。没有修改操作。

package 可变参数的使用;

import java.util.Arrays;
import java.util.List;
import java.util.Set;

public class ArgsDemo {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello","world","java");

        //list.add("javaee"); //UnsupportedOperationException
        //list.remove("hello"); //UnsupportedOperationException
        list.set(0,"hi");
        System.out.println(list);




        List<String>list2 = List.of("hello","world","java","java");
        // list2.add("java"); // UnsupportedOperationException
        //list2.remove("hello"); //UnsupportedOperationException

        //list2.set(0,"hi");//UnsupportedOperationException

        // Set<String> set = Set.of("hello","world","java","world"); //IllegalArgumentException
        Set<String> set = Set.of("hello","world","java");

        // set.add("javaee"); //UnsupportedOperationException
        // set.remove("javaee"); //UnsupportedOperationException
        // set集合没有带索引的方法,没有set方法。
        
        


    }
}