Java ArrayList.remove()未删除对象

Java ArrayList.remove()未删除对象,java,arraylist,Java,Arraylist,我知道这是一个混乱的实现,但我基本上有这段代码(我写了所有代码),我需要能够在使用适当的菜单选项时从列表中删除学生或讲师。代码中的其他所有内容都有效,只是菜单选项3和4无效。尝试删除时,我正在为对象输入完全相同的信息。这是密码。这三门课都在下面 驾驶员等级: import java.util.ArrayList; import java.util.Scanner; public class Driver { private ArrayList<Student> students;

我知道这是一个混乱的实现,但我基本上有这段代码(我写了所有代码),我需要能够在使用适当的菜单选项时从列表中删除学生或讲师。代码中的其他所有内容都有效,只是菜单选项3和4无效。尝试删除时,我正在为对象输入完全相同的信息。这是密码。这三门课都在下面

驾驶员等级:

import java.util.ArrayList;
import java.util.Scanner;

public class Driver {
private ArrayList<Student> students;
private ArrayList<Instructor> instructors;

public static void main(String[] args) {        
    Driver aDriver = new Driver();
    aDriver.run();      
}

public Driver() {
    students = new ArrayList<Student>();
    instructors = new ArrayList<Instructor>();
}

private void run() {
    Student aStudent;
    Instructor anInstructor;
    Scanner inp = new Scanner(System.in);
    int choice = -1;
    String str = "Enter a menu option:\n";

    str += " 0: Quit\n";
    str += " 1: Add new student\n";
    str += " 2: Add new instructor\n";
    str += " 3: Delete existing student\n";
    str += " 4: Delete existing instructor\n";
    str += " 5: Print list of students\n";
    str += " 6: Print list of instructors\n";
    str += "Your choice: ";

    do {
        System.out.print(str);
        choice = inp.nextInt();

        switch(choice) {
        case 0:
            System.out.println("Thanks! Have a great day!");
            break;
        case 1:
            aStudent = getStudentInfo();
            addStudent(aStudent);
            break;
        case 2:
            anInstructor = getInstructorInfo();
            addInstructor(anInstructor);
            break;
        case 3:
            aStudent = getStudentInfo();
            deleteStudent(aStudent);
            break;
        case 4:
            anInstructor = getInstructorInfo();
            deleteInstructor(anInstructor);
            break;
        case 5:
            printStudents();
            break;
        case 6:
            printInstructors();
            break;
        default:
            System.out.println("Invalid menu item " + choice);  
        }
    }
    while(choice != 0);
}

public Student getStudentInfo() {
    Student aStudent;
    String name = null;
    String id = null;
    double GPA = 0.0;
    Scanner inp = new Scanner(System.in);

    System.out.print("\n\nEnter the student's name: ");
    name = inp.nextLine();
    System.out.print("Enter the student's ID: ");
    id = inp.nextLine();
    System.out.print("Enter the student's GPA: ");
    GPA = inp.nextDouble();

    aStudent = new Student(name, id, GPA);
    return aStudent;
}

public Instructor getInstructorInfo() {
    Instructor anInstructor;
    String name = null;
    String id = null;
    String dept = null;
    String email = null;
    Scanner inp = new Scanner(System.in);

    System.out.print("\n\nEnter the instructor's name: ");
    name = inp.nextLine();
    System.out.print("Enter the instructor's ID: ");
    id = inp.nextLine();
    System.out.print("Enter the instructor's department: ");
    dept = inp.nextLine();
    System.out.print("Enter the instructor's email address: ");
    email = inp.nextLine();

    anInstructor = new Instructor(name, id, dept, email);
    return anInstructor;
}

public void addStudent(Student aStudent) {
    students.add(aStudent);
}

public void addInstructor(Instructor anInstructor) {
    instructors.add(anInstructor);
}

public void deleteStudent(Student aStudent) {
    students.remove(aStudent);
}

public void deleteInstructor(Instructor anInstructor) {
    instructors.remove(anInstructor);
}

public void printStudents() {
    System.out.println("\n\n" + Student.printHeader());

    for(int i = 0; i < students.size(); i++) {
        System.out.print(students.get(i));
    }

    System.out.print("\n\n");
}

public void printInstructors() {
    System.out.print("\n\n" + Instructor.printHeader());

    for(int i = 0; i < instructors.size(); i++) {
        System.out.print(instructors.get(i));
    }

    System.out.print("\n\n");
}
}
讲师课程:

public class Instructor {
private String name;
private String id;
private String dept;
private String email;

public Instructor() {
    name = "TestFirst TestLast";
    id = "-00001";
    dept = "TestDept";
    email = "test@test.net";
}

public Instructor(String name1, String id1, String dept1, String email1) {
    name = name1;
    id = id1;
    dept = dept1;
    email = email1;
}

public static String printHeader() {
    String str = String.format("%-30s%-6s%-15s%-15s\n", "Name", "ID", "Department", "Email Address");
    return str;
}

public String toString() {
    String str = String.format("%-30s%-6s%-15s%-15s\n", name, id, dept, email);
    return str;
}

public String getName() {
    return name;
}
}

对于
学生
讲师
课程,必须正确重写
equals()
方法

当重写equals时,最好也重写
hashCode()
。 新生(姓名、身份证、GPA)

例如,类似这样的内容:

public boolean equals(Object o) {
  if (!(o instanceof Student)) {
    return false;
  }
  Student other = (Student) o;
  return name.equals(other.name) && id.equals(other.id) && GPA == other.GPA;
}

public int hashCode() {
  return name.hashCode();
}
这样,您就有机会让
ArrayList
找出哪个对象对应于删除时作为参数传递的对象。如果不重写上述方法,它将使用
对象
中的默认实现,在删除新的
学生
对象时,这些实现会比较内存地址,这些地址肯定不同


您可以阅读javadocs for
Object

中关于这两个方法的更多信息,您需要覆盖equals和hashcode方法才能使集合正常工作

@Override
public boolean equals(Object obj) {
    if (obj == null)
        return false;
    if (!(obj instanceof Student))
        return false;
    Student other = (Student) obj;
    return id == null ? false : id.equals(other.id);//Compare Id if null falseF
}
因为您只使用ArrayList,所以不会使用hashcode方法,但提供它仍然是一个很好的实践

 @Override
public int hashCode() {
    return id == null ? 0 : id.hashCode();
}

您没有覆盖
学生
讲师
的方法

ArrayList
使用此方法检查两个对象是否相同。如果没有自定义实现,它只会检查引用,这在您的情况下是不同的,因为它们是两个不同的对象


要提供自定义相等,必须检查所涉及类的所有字段是否相同。这可以通过对实例变量调用
equals
递归完成。

覆盖Student和讲师的equals方法将起作用:

以下是学生班的一个示例:

public class Student {
private String name;
private String id;   //String to allow for the possibility of leading zeroes
private double GPA;

public Student() {
    name = "TestFirst TestLast";
    id = "00000";
    GPA = -1.00;
}

public Student(String name1, String id1, double GPA1) {
    name = name1;
    id = id1;
    GPA = GPA1;
}

public static String printHeader() {
    String str = String.format("%-25s%-7s%-6s\n", "Name", "ID", "GPA");
    return str;
}

public String toString() {
    String str = String.format("%-25s%-7s%-6.3f\n", name, id, GPA);
    return str;
}

public String getName() {
    return name;
}

public void setGPA(double GPA2) {
    GPA = GPA2;
}
}
public boolean equals(Object other){
    if(other == null) return false;
    if(other == this) return true;
    if(!(other instanceof Student)) return false;
    Student otherStudent = (Student)other;
    return otherStudent.id.equals(this.id);
}
您可能还希望覆盖
hashCode()


当存在同名的不同学生时,hashCode不会产生问题吗?不会,因为hashCode()的目标是将实例分离到存储桶中。只有同一个bucket中的实例使用equals进行比较。所以,同名学生应该进入同一个桶。你看到我更新的答案了吗?有一些代码可以复制并粘贴到其中。尽管如此,更好的hashCode重写可能会考虑id,而不是名称或名称之外的id。冲突会减少(假设学生id是唯一的)。不过,如果你不介意帮我核实的话,我想确保我理解。
对象o
参数是一个占位符,它将接受传递给它的任何
对象。if语句检查它是否是适当类型的对象(在本例中为
学生
,但在
讲师
类中为
讲师
),如果对象不是该类型,则返回false。行
Student other…
只是将
对象
放入一个
Student
对象中,以便对其进行比较,最终语句实际上检查上述内容是否相等。对吗?好吧,我明白你的意思,但我不知道如何实施。例如,当我重写
toString
时,我需要做的就是从该方法返回一个
String
对象。当我重写
equals
时,我需要使用if语句进行比较,但是我应该比较哪两件事,特别是在使用
ArrayList.remove()时
remove()。您只需要实现该方法,以便当且仅当两个学生是同一个学生时(这可能意味着如果他们有相同的名称和相同的内容,则返回
true
public String hashCode(){
    return new HashCodeBuilder(17, 31).
        append(name).
        append(id).
        toHashCode();
}