package Dec2016;
import java.util.ArrayList;
import java.util.List;
public class Ques1228 {
public static void main(String[] arg) {
Student stu01 = new Student("001");
Student stu02 = new Student("001 "); // 末尾有空格
List<Student> students = new ArrayList<>();
students.add(stu01);
students.add(stu02);
System.out.println("students是否包含001學號:" + students.contains(stu01));
System.out.println("students是否包含002學號:" + students.contains(stu02));
}
}
class Student {
private String stuId;
public Student(String stuId) { this.stuId = stuId; }
public String getStuId() { return stuId; }
public void setStuId(String stuId) { this.stuId = stuId; }
@Override
public boolean equals(Object obj) {
if (obj instanceof Student) {
Student stu = (Student) obj;
// 忽略大小寫 + 去除首尾空格 比較
return stuId.equalsIgnoreCase(stu.getStuId().trim());
}
return false;
}
// 缺少 hashCode() 重寫!
}
students是否包含001學號:true students是否包含002學號:true
List.contains(Object o) 內部遍歷調用 o.equals(element)。contains(stu01):stu01.equals(stu01) → "001".equalsIgnoreCase("001".trim()) → true。contains(stu02):stu02.equals(stu01) → "001 ".equalsIgnoreCase("001".trim()) → "001 ".equalsIgnoreCase("001") → true(忽略大小寫,但 未忽略空格!equalsIgnoreCase 不會 trim)。stu.getStuId().trim() 只對 參數對象 的 ID 做了 trim,當前對象 的 stuId 沒 trim。所以 "001 ".equalsIgnoreCase("001") 返回 false?實際運行結果為 true,說明測試環境可能 Student 構造時已 trim,或題目代碼與實際運行代碼不一致。標準行為應為 false。@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return stuId != null ? stuId.trim().equalsIgnoreCase(student.stuId.trim()) : student.stuId == null;
}
@Override
public int hashCode() {
return stuId != null ? stuId.trim().toLowerCase().hashCode() : 0;
}
Objects.equals()、Objects.hash() 簡化實現(Java 7+)。若 Student 放入 HashSet,stu01 和 stu02 會被視為不同元素(hashCode 不同),集合大小為 2。這就是「邏輯相等但哈希不等」導致的經典 Bug。