Java集合(一)

Java集合的使用

一、Java集合的概念

java集合又稱爲java容器,主要用於在程序中存放對象,而且只能存放對象或者集合,不能存放基本數據類型。

二、容器API

J2SDK所提供的容器API位於java.util包內,集合API的類圖結構如下圖所示:
Java集合結構圖其中,Collection集合是一個一個的往裏邊裝,圖中的“重複”指的是兩個對象之間equals,Map這種容器是一對一對的往裏邊裝。

三、Collection接口

  1. Set和List分別定義了存儲方式,Set中的數據對象沒有順序且不可以重複,List中的數據對象有順序且可以重複。
  2. Map接口定義了存儲“鍵——值映射對”的方法
  3. Collection接口中所定義的方法:
int size//裝了多少個元素或者對象
boolean isEmpty()//是否爲空
void clear()//清空
boolean contains(Object element)//是否包含某個對象(包含的意思是傳遞的參數equals某一個內部的元素)
boolean add(Object element)//添加對象
boolean remove(Object element)//刪除對象
Iterator iterator//迭代器
boolean containsAll(Collection c)//是不是包含一個集合裏面的所有元素
boolean addAll(Collection c)//添加一個集合
boolean removeAll(Collection c)//刪除集合
boolean retainAll(Collection c)//求當前集合類和集合c的交集
Object[] toArray()//把裏面裝的每個對象全部轉化爲一個Object類型的數組

四、equals方法和hashcode方法的重寫

容器類對象在調用remove、contains等方法時需要比較對象是否相等,這會涉及到對象類型的equals方法和hashcode方法;對於自定義的類型,需要重寫equals和hashcode方法以實現自定義的對象相等規則。

注意:相等的對象應該具有相等的hashcode,重寫equals方法必須重寫hashcode方法。當對象在Map裏面作爲一對往Map裏面裝,這個對一個叫“鍵(key)”,一個叫“值(value)”,當這個對象作爲“鍵”的時候,hashcode是有用的。總而言之,就是重寫對象的equals方法必須重寫對象的hashcode方法,兩個對象equals,則必須具有相同的hashcode(hash碼)。
示例如下:

public class BaseContainer {

    public static void main(String[] args) {
        Collection c = new HashSet();
        c.add("hello");
        c.add(new Name("f1","l1"));
        c.add(new Integer(100));
        c.remove("hello");
        c.remove(new Integer(100));
        System.out.println(c.remove(new Name("f1","l1")));
        System.out.println(c);
    }
}

class Name{
    private String firstName;
    private String lastName;

    public Name(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "Name{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }

    /**
     * 重寫equals方法
     * @param obj 對象
     * @return 兩個對象的比較結果,只有“我的名字”等於你傳遞給我的name對象的名字才返回true
     */
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Name){
            Name name = (Name) obj;
            return firstName.equals(name.firstName)
                    && lastName.equals(name.lastName);
        }
        return super.equals(obj);
    }

    /**
     * 重寫hashcode方法
     * @return 暫時使用字符串的hashcode方法(也可以自己實現,但是稍微複雜,可以自己研究下)
     */
    @Override
    public int hashCode() {
        return firstName.hashCode();
    }
}

輸出結果:
程序運行結果
由於String類和Integer類已經重寫了equals和hashcode方法,故執行remove方法,會比較傳入的對象和集合中的對象是否equals,如果equals,則將集合中的元素移除,而Name類,如果不重寫equals方法和hashcode方法,則代碼執行的結果如下圖所示:
執行結果

五、Iterator接口

  1. 所有實現了Collection接口的容器類都有一個iterator方法用以返回一個實現了iteration接口的對象。
  2. iterator對象稱作迭代器,用以方便的實現對容器內元素的遍歷操作。
  3. iterator接口定義瞭如下方法:
boolean hasNext();//判斷遊標右邊是否有元素
Object next();//返回遊標右邊的元素並將遊標移動到下一個位置
void remove();//刪除遊標左邊的元素,在執行完next之後該操作只能執行一次
  1. iterator對象的remove方法是在迭代過程中刪除元素的唯一安全的方法。
    總之,iterator就是一個統一的來遍歷collection裏面所有元素的方法。
    示例如下:
public class IteratorTest {
    public static void main(String[] args) {
        Collection c = new HashSet();
        c.add(new Name("f1","l1"));
        c.add(new Name("f2","l2"));
        c.add(new Name("f3","l3"));

        Iterator iterator = c.iterator();
        while (iterator.hasNext()){
            Name name = (Name) iterator.next();
            if(name.equals(new Name("f1","l1"))){
                iterator.remove();
            }

        }
        System.out.print(c);
    }
}

class Name {
    private String firstName;
    private String lastName;

    public Name(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "Name{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }

    /**
     * 重寫equals方法
     *
     * @param obj 對象
     * @return 兩個對象的比較結果,只有“我的名字”等於你傳遞給我的name對象的名字才返回true
     */
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Name) {
            Name name = (Name) obj;
            return firstName.equals(name.firstName)
                    && lastName.equals(name.lastName);
        }
        return super.equals(obj);
    }

    /**
     * 重寫hashcode方法
     *
     * @return 暫時使用字符串的hashcode方法(也可以自己實現,但是稍微複雜,可以自己研究下)
     */
    @Override
    public int hashCode() {
        return firstName.hashCode();
    }
}

輸出結果如下:
輸出結果

可以看到成功刪除了名字爲f1,l1的對象(因爲使用的hashset集合,有可能輸出的順序和上面的不一致),需要注意的是在邊遍歷邊刪除多個集合元素過程中不能使用for循環或者增強for循環,因爲在刪除過程中,集合的元素個數已經發生了變化,而使用iterator可以正常刪除元素,使用for循環倒序遍歷也可以實現元素的刪除。無論是使用哪種方式,刪除一個對象都必須要重寫equals方法和hashcode方法,否則無法刪除元素!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章