Java集合框架(下)之List與Set的contains()方法
Java集合框架(上)介紹了List與Set的基本用法:增刪改查,Java集合框架(中)介紹了Map的基本用法:增刪改查。但是還不夠運用於實際應用,下面就開始介紹List與Set中是否包含某元素的用法。
List的contains()使用(ListContains.java)
package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class ListContains {
private Scanner sc;
public List<Course> CoursesToSelect;
public ListContains(){
this.CoursesToSelect = new ArrayList<Course>();
sc = new Scanner(System.in);
}
public void TestAdd(){
Course cr1 = new Course("1","資料結構");
CoursesToSelect.add(cr1);
Course cr2 = new Course("2","常用演算法");
CoursesToSelect.add(0, cr2);
Course[] courseList = {new Course("3","Javaweb"),new Course("4","資料庫")};
CoursesToSelect.addAll(Arrays.asList(courseList));
Course[] courseList2 = {new Course("5","高等數學"),new Course("6","計算機網路")};
CoursesToSelect.addAll(2 ,Arrays.asList(courseList2));
}
public void testForEach(){
for(Course course:CoursesToSelect){
System.out.println("課程:"+course.name+" 課程id:"+course.id);
}
}
public void testListContains(){//測試List是否包含某個元素
Course course = CoursesToSelect.get(0);
System.out.println("取得課程:"+course.name);
System.out.println("備選課程中是否包含課程:"+course.name+","+
CoursesToSelect.contains(course));
Course cr = new Course(course.id,course.name);
System.out.println("新建課程:"+cr.name);
System.out.println("備選課程中是否包含課程:"+cr.name+","+
CoursesToSelect.contains(cr));
/*這裡輸出false,因為比較方法用的是Object中的equals(),只要地址不同,就返回false.(不是字串)
若想通過只比較課程名字判斷是否含有該課程,要重寫Course類中的equals方法
*/
}
public static void main(String[] args){
ListContains lc = new ListContains();
lc.TestAdd();
lc.testForEach();
lc.testListContains();
}
}
執行結果:
課程:常用演算法 課程id:2
課程:資料結構 課程id:1
課程:高等數學 課程id:5
課程:計算機網路 課程id:6
課程:Javaweb 課程id:3
課程:資料庫 課程id:4
取得課程:常用演算法
備選課程中是否包含課程:常用演算法,true
新建課程:常用演算法
備選課程中是否包含課程:常用演算法,false
結果分析:
- 先要說說List中contains()的原理:遍歷List中的每個元素,每個元素與比較物件進行equals()比較,只要有一個相同,就返回true(原理可以在原始碼中找到)。
- 如果你不懂這裡第一個輸出是true,第二個輸出是false的原因,可以參考程式碼中的註釋,如果還不懂,相信看完equals()與==的區別與實際應用,你就會明白。
- 如果我想根據課程名字判斷是否包含某門課程怎麼辦?很簡單也很清楚,重寫equals()方法。
Course.java中重寫equals():
@Override
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)){//字串物件比較,當然直接用equals()
return true;
}
else{
return false;
}
}
}
再次執行得到執行結果:
課程:常用演算法 課程id:2
課程:資料結構 課程id:1
課程:高等數學 課程id:5
課程:計算機網路 課程id:6
課程:Javaweb 課程id:3
課程:資料庫 課程id:4
取得課程:常用演算法
備選課程中是否包含課程:常用演算法,true
新建課程:常用演算法
備選課程中是否包含課程:常用演算法,true
Set的contains()使用(SetContains.java)
package com.imooc.collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class SetContains {
private Scanner sc;
private Student student;
public List<Course> CoursesToSelect;
public SetContains(){
this.CoursesToSelect = new ArrayList<Course>();
sc = new Scanner(System.in);
}
public void TestAdd(){
Course cr1 = new Course("1","資料結構");
CoursesToSelect.add(cr1);
Course cr2 = new Course("2","常用演算法");
CoursesToSelect.add(0, cr2);
Course[] courseList = {new Course("3","Javaweb"),new Course("4","資料庫")};
CoursesToSelect.addAll(Arrays.asList(courseList));
Course[] courseList2 = {new Course("5","高等數學"),new Course("6","計算機網路")};
CoursesToSelect.addAll(2,Arrays.asList(courseList2));
}
public void testForEach(){
for(Course course:CoursesToSelect){
System.out.println("課程:"+course.name+" 課程id:"+course.id);
}
}
/*建立學生物件並選課*/
public void createStudentsAndSelectCourses(){
//建立一個學生物件
student = new Student("1","小明");
System.out.println("歡迎"+student.name+"選課!");
for(int i=0;i<3;i++){
System.out.println("請輸入課程ID:");
String courseId = sc.next();
for(Course course:CoursesToSelect){
if(course.id.equals(courseId)){ //字串是物件,其equals()方法比較的是實際內容!
student.courses.add(course);
}
}
}
}
/*測試Set的contains()方法*/
public void testSetContains(){
System.out.println("請輸入學生已選的課程名稱:");
String name = sc.next();
Course cr = new Course();
cr.name = name;
System.out.println("新建課程:"+cr.name);
System.out.println("備選課程中是否包含課程:"+cr.name+","+
student.courses.contains(cr));
}
public static void main(String[] args){
SetContains sc = new SetContains();
sc.TestAdd();
sc.testForEach();
sc.createStudentsAndSelectCourses();
sc.testSetContains();
}
public void testForEachForSet(Student stu){
System.out.println("共選擇了"+stu.courses.size()+"門課程");
for(Course course:stu.courses){
System.out.println(stu.name+"選擇了"+course.name+" 課程id:"+course.id);
}
}
}
執行結果:
課程:常用演算法 課程id:2
課程:資料結構 課程id:1
課程:高等數學 課程id:5
課程:計算機網路 課程id:6
課程:Javaweb 課程id:3
課程:資料庫 課程id:4
歡迎小明選課!
請輸入課程ID:
2
請輸入課程ID:
1
請輸入課程ID:
5
請輸入學生已選的課程名稱:
常用演算法
新建課程:常用演算法
備選課程中是否包含課程:常用演算法,false
結果分析:
- 學生選了的課中包含了常用演算法這門課程,從程式碼中可以看到,新建了一個名字叫常用演算法的課程與Set中的課程比較,看是否包含,很明顯跟List的測試一樣,課程名字一樣,但是輸出卻是false。
- 那Set中的contains()方法的原理是什麼?能確定的是跟List的不一樣,因為在List中已經重寫了equals()方法,若Set的contains()原理與List的相同,那麼這裡的結果應該是true,但是這裡是false。
- 原來,在Object類中除了定義equals()方法,還定義了hashCode()的方法,返回的是物件的雜湊碼(雜湊碼是物件的記憶體地址字串,物件不同,記憶體地址就不同,雜湊碼就不同)。當我們呼叫Set的contains()方法時,會先呼叫每個元素的hashCode()方法,如果返回的值與比較物件相同,再呼叫equals()方法,只有在這兩個方法的值都相等的情況下,才可認定這個Set包含某個元素。
- 因此在測試中新建了物件,雜湊碼當然會不同,所以就算重寫了equals()方法,得到的結果還是false。要使其輸出是true,要在Course.java中重寫hashCode()方法,配合之前重寫的equals()方法,就能達到目的。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
重新執行程式,得到執行結果:
課程:常用演算法 課程id:2
課程:資料結構 課程id:1
課程:高等數學 課程id:5
課程:計算機網路 課程id:6
課程:Javaweb 課程id:3
課程:資料庫 課程id:4
歡迎小明選課!
請輸入課程ID:
2
請輸入課程ID:
3
請輸入課程ID:
6
請輸入學生已選的課程名稱:
計算機網路
新建課程:計算機網路
備選課程中是否包含課程:計算機網路,true