飞道的博客

Java基础 学习笔记9

288人阅读  评论(0)

前言:本笔记中内容将继续完善笔记7,8中相关代码的功能,请先观看笔记7,8中相关代码,了解原理后再来学习本笔记中内容:
Java基础 学习笔记7
Java基础 学习笔记8

1.学生选课-判断List中课程是否存在
新建一个SetTest2类,里面很多代码和SetTest中是完全一致的:

package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class SetTest2 {
    public List<Course> coursesToSelect; //带有泛型Course的List类型属性
    public SetTest2() {
        this.coursesToSelect = new ArrayList<Course>();
    }

    public void testAdd() { //用于往coursesToSelect中添加备选课程
        //创建一个课程对象,并通过调用add方法,添加到备选课程List中
        Course cr1 = new Course("1", "数据结构");
        coursesToSelect.add(cr1);
        Course cr2 = new Course("2", "C语言");
        coursesToSelect.add(0, cr2);
        Course[] course = {new Course("3", "离散数学"), new Course("4", "汇编语言")};
        //add方法是用来添加单个的Course对象的,而addAll方法是将一个集合List里的所有元素都添加到courseToSelect集合里去的。
        //Arrays.asList方法不是用来添加对象的,而是用来将Course数组转化为集合的。
        coursesToSelect.addAll(Arrays.asList(course));
        Course[] course2 = {new Course("5", "高等数学"), new Course("6", "大学英语")};
        coursesToSelect.addAll(2, Arrays.asList(course2));
    }

    public void testListContains() {
        //取得备选课程序列的第0个元素
        Course course = coursesToSelect.get(0);
        //打印输出查看coursesToSelect是否包含course对象
        System.out.println("取得课程:" + course.name);
        System.out.println("备选课程中是否包含课程:" + course.name + "," + coursesToSelect.contains(course));
        //创建一个新的课程对象,ID和名称,与course对象完全一样
        Course course2 = new Course(course.id, course.name);
        System.out.println("新创建课程:" + course2.name);
        System.out.println("备选课程中是否包含课程:" + course2.name + "," + coursesToSelect.contains(course2));
    }

    public static void main(String[] args) {
        SetTest2 st = new SetTest2();
        st.testAdd();
        st.testListContains();
    }
}

运行结果:

第二次比较返回结果是false的原因:
contains实现原理:所有类都是继承Object类,Object类中的equals方法比较的是对象的引用是否指向同一块内存地址-(对象实例化时,即给对象分配内存空间)。调用List的contains方法时,会遍历集合中的元素,调用每一个元素的equals方法将集合中的元素与传入的对象一一比较,如果相同就会返回true,而新建的这个course2很明显不是集合中的元素(地址不同),所以会返回false。

那么如果我们向根据内容判断是否存在某个课程(即相同的名称就会返回true),那么我们就需要重写equals方法。有同学可能会有疑问,你的笔记前面介绍的String类中的equals方法就是比较内容的啊,这是因为在Java中,String 、Math、还有Integer、Double等这些封装类重写了Object中的equals()方法,让它不再比较其对象在内存中的地址,而是比较对象中实际包含的整数的值,即比较的是内容。
在Course类中重写equals方法:

public boolean equals(Object obj) {
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(!(obj instanceof Course))
            return false;
        Course course = (Course) obj;
        if(this.name == null) {
            if(course.name == null)
                return true;
            else
                return false;
        } else {
            if(this.name.equals(course.name))
                return true;
            else
                return false;
        }
    }

再次执行SetTest2中的主函数,运行结果如下:
那么如果我们想让用户从键盘上输入一个课程名称,并查找集合中是否存在该课程,我们应该怎么办呢?其实很简单,只需要对上述代码做少部分修改即可:

package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class SetTest2 {
    public List<Course> coursesToSelect; //带有泛型Course的List类型属性
    private Scanner console;
    public SetTest2() {
        this.coursesToSelect = new ArrayList<Course>();
        console = new Scanner(System.in);
    }

    public void testAdd() { //用于往coursesToSelect中添加备选课程
        //创建一个课程对象,并通过调用add方法,添加到备选课程List中
        Course cr1 = new Course("1", "数据结构");
        coursesToSelect.add(cr1);
        Course cr2 = new Course("2", "C语言");
        coursesToSelect.add(0, cr2);
        Course[] course = {new Course("3", "离散数学"), new Course("4", "汇编语言")};
        //add方法是用来添加单个的Course对象的,而addAll方法是将一个集合List里的所有元素都添加到courseToSelect集合里去的。
        //Arrays.asList方法不是用来添加对象的,而是用来将Course数组转化为集合的。
        coursesToSelect.addAll(Arrays.asList(course));
        Course[] course2 = {new Course("5", "高等数学"), new Course("6", "大学英语")};
        coursesToSelect.addAll(2, Arrays.asList(course2));
    }

    public void testListContains() {
        //取得备选课程序列的第0个元素
        Course course = coursesToSelect.get(0);
        //打印输出查看coursesToSelect是否包含course对象
        System.out.println("取得课程:" + course.name);
        System.out.println("备选课程中是否包含课程:" + course.name + "," + coursesToSelect.contains(course));
        //提示输入新的课程名称
        System.out.println("请输入课程名称:");
        String name = console.next();
        //创建一个新的课程对象,ID和名称,与course对象完全一样
        Course course2 = new Course();
        course2.name = name;
        System.out.println("新创建课程:" + course2.name);
        System.out.println("备选课程中是否包含课程:" + course2.name + "," + coursesToSelect.contains(course2));
    }

    public static void main(String[] args) {
        SetTest2 st = new SetTest2();
        st.testAdd();
        st.testListContains();
    }
}

运行结果:

containsAll方法:具体用法和前面详细介绍的removeAll等方法非常类似,具体不再赘述。

2.学生选课-判断Set中课程是否存在
写一个SetTest3类,也是在SetTest中的方法基础上进行改动的:

package com.imooc.collection;
import java.util.*;

public class SetTest3 {
    public List<Course> coursesToSelect; //带有泛型Course的List类型属性
    public Student student;
    private Scanner console = new Scanner(System.in);
    public SetTest3() {
        this.coursesToSelect = new ArrayList<Course>();
    }

    public void testAdd() { //用于往coursesToSelect中添加备选课程
        //创建一个课程对象,并通过调用add方法,添加到备选课程List中
        Course cr1 = new Course("1", "数据结构");
        coursesToSelect.add(cr1);
        Course cr2 = new Course("2", "C语言");
        coursesToSelect.add(0, cr2);
        Course[] course = {new Course("3", "离散数学"), new Course("4", "汇编语言")};
        //add方法是用来添加单个的Course对象的,而addAll方法是将一个集合List里的所有元素都添加到courseToSelect集合里去的。
        //Arrays.asList方法不是用来添加对象的,而是用来将Course数组转化为集合的。
        coursesToSelect.addAll(Arrays.asList(course));
        Course[] course2 = {new Course("5", "高等数学"), new Course("6", "大学英语")};
        coursesToSelect.addAll(2, Arrays.asList(course2));
    }

    //创建学生对象并选课
    public void createStudentAndSelectCourses() {
        //创建一个学生对象
        student = new Student("1", "小明");
        System.out.println("欢迎学生:" + student.name + "选课!");
        //创建一个Scanner对象,用来接收从键盘输入的课程ID
        Scanner console = new Scanner(System.in);
        for (int i = 0; i < 3; i++) {
            System.out.println("请输入课程ID:");
            String courseID = console.next();
            for (Course cr: coursesToSelect) {
                if(cr.id.equals(courseID)) {
                    student.courses.add(cr);
                    student.courses.add(cr); //验证Set中元素是不可重复的
                }
            }
        }
    }

    //测试Set的contains方法
    public void testSetContains() {
        //提示输入课程名称
        System.out.println("请输入学生已选的课程名称:");
        String name = console.next();
        //创建一个新的课程对象,ID和名称,与course对象完全一样
        Course course2 = new Course();
        course2.name = name;
        System.out.println("新创建课程:" + course2.name);
        System.out.println("备选课程中是否包含课程:" + course2.name + "," + student.courses.contains(course2));
    }

    public void testForEach() {
        System.out.println("有如下课程待选(通过for each访问):");
        for(Object obj: coursesToSelect) {
            Course cr = (Course)obj;
            System.out.println("课程:" + cr.id + ":" +  cr.name);
        }
    }

    public static void main(String[] args) {
        SetTest3 st = new SetTest3();
        st.testAdd();
        st.testForEach();
        st.createStudentAndSelectCourses();
        st.testSetContains();
    }
}

运行结果:

一个奇怪的问题出现了,为什么这里显示的是false呢?
这是因为courses集合我们是用HashSet实现的,而在调用HashSet的contains方法的时候,其实是先调用了hashCode方法来返回哈希码,在哈希码的值相等的情况下才调用equals方法去判断是否相等,只有都相等的情况下才能认定这个HashSet包含某个元素:

所以我们要重写hashCode方法:
在Course类中右键点击空白处,选择generate,选择生成hashCode和equals,选择name属性(因为我们只需要判断name),然后系统就会自动为我们生成这两个方法,可以看到,equals方法和我们之前重写的并无两样。之后再去执行SetTest3中的主函数,就会返回true了。

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

    public boolean equals(Object obj) {
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(!(obj instanceof Course))
            return false;
        Course course = (Course) obj;
        if(this.name == null) {
            if(course.name == null)
                return true;
            else
                return false;
        } else {
            if(this.name.equals(course.name))
                return true;
            else
                return false;
        }
    }

3.学生选课-获取List中课程的位置
写一个类SetTest4,也是对之前的代码做些改动:

package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class SetTest4 {
    public List<Course> coursesToSelect; //带有泛型Course的List类型属性
    private Scanner console;
    public SetTest4() {
        this.coursesToSelect = new ArrayList<Course>();
        console = new Scanner(System.in);
    }

    public void testAdd() { //用于往coursesToSelect中添加备选课程
        //创建一个课程对象,并通过调用add方法,添加到备选课程List中
        Course cr1 = new Course("1", "数据结构");
        coursesToSelect.add(cr1);
        Course cr2 = new Course("2", "C语言");
        coursesToSelect.add(0, cr2);
        Course[] course = {new Course("3", "离散数学"), new Course("4", "汇编语言")};
        //add方法是用来添加单个的Course对象的,而addAll方法是将一个集合List里的所有元素都添加到courseToSelect集合里去的。
        //Arrays.asList方法不是用来添加对象的,而是用来将Course数组转化为集合的。
        coursesToSelect.addAll(Arrays.asList(course));
        Course[] course2 = {new Course("5", "高等数学"), new Course("6", "大学英语")};
        coursesToSelect.addAll(2, Arrays.asList(course2));
    }

    public void testListContains() {
        //取得备选课程序列的第0个元素
        Course course = coursesToSelect.get(0);
        //打印输出查看coursesToSelect是否包含course对象
        System.out.println("取得课程:" + course.name);
        System.out.println("备选课程中是否包含课程:" + course.name + "," + coursesToSelect.contains(course));
        //提示输入新的课程名称
        System.out.println("请输入课程名称:");
        String name = console.next();
        //创建一个新的课程对象,ID和名称,与course对象完全一样
        Course course2 = new Course();
        course2.name = name;
        System.out.println("新创建课程:" + course2.name);
        System.out.println("备选课程中是否包含课程:" + course2.name + "," + coursesToSelect.contains(course2));
        //通过indexOf方法来取得某元素的索引位置
        if(coursesToSelect.contains(course2))
            System.out.println("课程:" + course2.name + "的索引位置为" + coursesToSelect.indexOf(course2));
    }

    public void testForEach() {
        System.out.println("有如下课程待选(通过for each访问):");
        for(Object obj: coursesToSelect) {
            Course cr = (Course)obj;
            System.out.println("课程:" + cr.id + ":" +  cr.name);
        }
    }

    public static void main(String[] args) {
        SetTest4 st = new SetTest4();
        st.testAdd();
        st.testListContains();
        st.testForEach();
    }
}

运行结果:


indexOf()方法与lastIndexOf()方法实现原理:
a.遍历调用每个元素的equals()方法,如果返回true则将次元素的索引返回
b.如果有多个相同元素,则只返回第一个元素的索引
c.lastIndexOf()方法则从最后一个元素开始遍历
d.indesOf 和lastIndexOf 方法如果未找到相关元素的话,返回值为-1


转载:https://blog.csdn.net/weixin_43684054/article/details/104655489
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场