1. 程式人生 > >Java集合框架(下)之List與Set的contains()方法

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

結果分析:

  1. 先要說說List中contains()的原理:遍歷List中的每個元素,每個元素與比較物件進行equals()比較,只要有一個相同,就返回true(原理可以在原始碼中找到)。
  2. 如果你不懂這裡第一個輸出是true,第二個輸出是false的原因,可以參考程式碼中的註釋,如果還不懂,相信看完equals()與==的區別與實際應用,你就會明白。
  3. 如果我想根據課程名字判斷是否包含某門課程怎麼辦?很簡單也很清楚,重寫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

結果分析:

  1. 學生選了的課中包含了常用演算法這門課程,從程式碼中可以看到,新建了一個名字叫常用演算法的課程與Set中的課程比較,看是否包含,很明顯跟List的測試一樣,課程名字一樣,但是輸出卻是false。
  2. 那Set中的contains()方法的原理是什麼?能確定的是跟List的不一樣,因為在List中已經重寫了equals()方法,若Set的contains()原理與List的相同,那麼這裡的結果應該是true,但是這裡是false。
  3. 原來,在Object類中除了定義equals()方法,還定義了hashCode()的方法,返回的是物件的雜湊碼(雜湊碼是物件的記憶體地址字串,物件不同,記憶體地址就不同,雜湊碼就不同)。當我們呼叫Set的contains()方法時,會先呼叫每個元素的hashCode()方法,如果返回的值與比較物件相同,再呼叫equals()方法,只有在這兩個方法的值都相等的情況下,才可認定這個Set包含某個元素。
  4. 因此在測試中新建了物件,雜湊碼當然會不同,所以就算重寫了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