天天看點

Java之Set接口

轉自:https://www.cnblogs.com/chanshuyi/p/4468470.html

一、Set接口

Set 接口與 List 接口相比沒有那麼多操作方法,比如:

1、List 接口能直接設定或擷取某個元素的值,而Set接口不能。

2、List 接口能直接在指定位置删除、增加元素,而Set接口不能。

3、List 接口有 listIterator 方法,可以獲得 ListIterator 對象,而 Set 接口不能。Set 隻能通過 iterator 疊代的方式擷取元素。

對比一下Set接口和Collection接口就知道,其實Set接口僅僅對Collection所有方法進行繼承而已,而自己沒有擴充任何方法,Set接口與Collection接口一樣,都是15個方法。

Java之Set接口

Set不允許包含相同的元素,如果試圖把兩個相同元素加入同一個集合中,add方法傳回false。這裡說的相同元素指的是用 equals() 方法比價後傳回 true,當然了如果用 == 也傳回true,那肯定也是相同的。

二、HashSet實作類

Java之Set接口

HashSet 實作類與 Set 接口在方法上的唯一差別就是 HashSet 多了一個clone()方法。

hashSet 有以下特點:

· 不能保證元素的排列順序,順序有可能發生變化

· 不是同步的

· 集合元素可以是 null,但隻能放入一個 null

一般操作 HashSet 還是調用 Collection 的 add / remove 等方法進行操作

package com.chanshuyi.collection.set;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetTest {

    public static void main(String[] args) {
        //增加
        Set<String> hashSet = new HashSet<String>();
        hashSet.add("1");
        hashSet.add("2");
        hashSet.add("3");
        hashSet.add("4");
        hashSet.add("5");
        
        //删除
        hashSet.remove("1");
        
        //查詢  無法擷取某個元素
        System.out.println("是否包含1元素:" + hashSet.contains("2"));
        
        //疊代
        Iterator<String> it = hashSet.iterator();
        while(it.hasNext()){
            System.out.print(it.next() + " ");
        }        
    }
}
           

當向 HashSet 結合中存入一個元素時,HashSet 會調用該對象的 hashCode() 方法來得到該對象的hashCode值,然後根據 hashCode值來決定該對象在 HashSet 中存儲位置。根據這種方式可以看出,HashSet 的資料存取其實是通過雜湊演算法實作的,因為通過雜湊演算法可以極大的提高資料的讀取速度。通過閱讀 JDK 源碼,我們知道 HashSet 是通過 HashMap 實作的,隻不過是HashSet 的 value 上的值都是 null 而已。

簡單的說,HashSet 集合判斷兩個元素相等的标準是兩個對象通過 equals() 方法比較相等,并且兩個對象的hashCode() 方法傳回值相等。

注意,如果要把一個對象放入 HashSet 中,重寫該對象對應類的 equals() 方法,也應該重寫其 hashCode() 方法。其規則是如果兩個對 象通過equals方法比較傳回true時,其hashCode也應該相同。另外,對象中用作equals比較标準的屬性,都應該用來計算hashCode的值。

三、LinkedHashSet實作類

Java之Set接口

LinkedHashSet類繼承了HashSet類,實作了Set接口。其操作方法也是跟HashSet一樣,全部來自于Set接口,一共有15個方法。

LinkedHashSet 集合同樣是根據元素的 hashCode 值來決定元素的存儲位置,但是它同時使用連結清單維護元素的次序。

這樣使得元素看起來像是以插入順序儲存的,也就是說,當周遊該集合時候,LinkedHashSet将會以元素的添加順序通路集合的元素。

LinkedHashSet 在疊代通路 Set 中的全部元素時,性能比 HashSet 好,但是插入時性能稍微遜色于HashSet(因為 HashSet 直接采用雜湊演算法,而 LinkedHashSet 還需要維護連結清單結構)。

package com.chanshuyi.collection.set;

import java.util.LinkedHashSet;

public class LinkedHashSetTest {

    public static void main(String[] args) {
        //增加
        LinkedHashSet<String> linkedSet = new LinkedHashSet<String>();
        linkedSet.add("1");
        linkedSet.add("2");
        linkedSet.add("3");
        linkedSet.add("4");
        
        //删除 
        linkedSet.remove("2");
        
        //查詢    無法擷取某個确定元素,沒有get()方法
        System.out.println("是否包含元素4:" + linkedSet.contains("4"));
        
        for(String num : linkedSet){
            System.out.print(num + " ");
        }
    }
}
           

四、TreeSet實作類

Java之Set接口

TreeSet 是 SortedSet 接口的唯一實作類,TreeSet 可以確定集合元素處于排序狀态,這也是 TreeSet最大的特征之一。

TreeSet支援兩種排序方式,自然排序和定制排序,其中自然排序為預設的排序方式。向TreeSet中加入的應該是同一個類的對象。插入 TreeSet 中的對象使用一個外部比較器或者對象實作排序接口。

1、JavaBean中實作Comparable接口的compareTo()方法

自然排序使用要排序元素的 CompareTo(Object obj)方法來比較元素之間大小關系,然後将元素按照升序排列。

Java提供了一個 Comparable 接口,該接口裡定義了一個 compareTo(Object obj) 方法,該方法傳回一個整數值,實作了該接口的對象就可以比較大小。

obj1.compareTo(obj2) 方法如果傳回 0,則說明被比較的兩個對象相等,如果傳回一個正數,則表明obj1大于obj2,如果是 負數,則表明obj1小于obj2。

如果我們将兩個對象的equals方法總是傳回true,則這兩個對象的 compareTo 方法傳回應該傳回0

package com.chanshuyi.collection.set;

import java.util.TreeSet;

/**
 * 構造JavaBean并實作Comparable接口的compareTo方法
 * @author Administrator
 */
public class TreeSetTest2 {

    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<Student>();
        treeSet.add(new Student("Tpple", 12));
        treeSet.add(new Student("Tpple", 10));
        
        for(Student s : treeSet){
            System.out.println(s);
        }
    }
}

class Student implements Comparable<Student>{
    private String name;
    
    private int age;
    
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Student s) {
        if(this.age > s.getAge()){
            return 1;    //按照自然排序
        }else if(this.age == s.getAge()){
            return 0;
        }else{
            return -1;
        }        
    }
    
    public String toString(){
        return "[" + this.name + "," + this.age + "]";
    }
}
           

2、建構自定義比較器(實作Comparator接口)

自然排序是根據集合元素的大小,以升序排列,如果要定制排序,應該使用Comparator接口,實作 int compare(T o1,T o2)方法

package com.chanshuyi.collection.set;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetTest3 {

    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<Student>(new MyComparator());
        treeSet.add(new Student("Tpple", 12));
        treeSet.add(new Student("Tpple", 10));
        
        for(Student s : treeSet){
            System.out.println(s);
        }
    }
}

class MyComparator implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
        if(o1.getAge() > o2.getAge()){
            return 1;     
        }else if(o1.getAge() == o2.getAge()){
            return 0;
        }else{
            return -1;
        }    
    }
}