1. 程式人生 > 實用技巧 >Java基礎之:Set——HashSet——LinkedHashSet

Java基礎之:Set——HashSet——LinkedHashSet

Java基礎之:Set——HashSet——LinkedHashSet

LinkedHashSet簡單介紹

  1. LinkedHashSet是HashSet的子類

  2. LinkedHashSet根據元素的hashCode值來決定元素的儲存位置,但它同時使用連結串列維護元素的次序,這使得元素看起來是以插入順序儲存的。

  3. LinkedHashSet新增效能略低於HashSet,但在迭代訪問Set裡的全部元素時有很好的效能。(因為底層維護了一個hash表+雙向連結串列)

  4. LinkedHashSet底層是一個LinkedHashMap,維護的連結串列是一個雙向連結串列。

使用案例:

package class_TreeSet_LinkedHashSet;
​
import java.util.LinkedHashSet;
import java.util.Set;
​
public class ClassTest02_LinkedHashSet {
​
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String[] args) {
​
        Set set = new LinkedHashSet();
        set.add(new String("AA"));
        set.add(456);
        set.add(456);
        set.add(new Customer("劉",1001));
        set.add(123);
        
        System.out.println(set);
    }
}
​
class Customer{
    private String name;
    private int id;
    public Customer(String name, int id) {
        super();
        this.name = name;
        this.id = id;
    }
    @Override
    public String toString() {
        return "Customer [name=" + name + ", id=" + id + "]";
    }
}

案例說明:

  1. 在LinkedHastSet 中維護了一個hash表和雙向連結串列( LinkedHashSet 有 head 和 tail )

  2. 每一個節點有 pre 和 next 屬性, 這樣可以形成雙向連結串列。

  3. 在新增一個元素時,先求hash值,在求索引., 確定該元素在hashtable的位置,然後將新增的元素加入到雙向連結串列(如果已經存在,不新增[原則和hashset一樣])。

  4. 這樣的話,我們遍歷LinkedHashSet 也能確保插入順序和遍歷順序一致。

簡單使用案例

使用的Car 類(屬性:name,price), 需要重寫hashCode和equlas 方法. 如果 name 和 price 一樣,就不能加入到LinkedHashSet

package class_TreeSet_LinkedHashSet;
import java.util.LinkedHashSet;
public class ClassWork01 {
​
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String[] args) {
​
        Car car1 = new Car("蔚來SE",460000);
        Car car2 = new Car("吉普",660000);
        Car car3 = new Car("蔚來SE",460000);
        
        LinkedHashSet linkedHashSet = new LinkedHashSet();
        
        linkedHashSet.add(car1);
        linkedHashSet.add(car2);
        linkedHashSet.add(car3);
        
        for(Object obj:linkedHashSet) {
            System.out.println(obj);
        }
    }
​
}
​
class Car{
    private String name;
    private double price;
    
    public Car(String name, double price) {
        super();
        this.name = name;
        this.price = price;
    }
    
    @Override
    public String toString() {
        return "Car [name=" + name + ", price=" + price + "]";
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    
    //可以自己定義對比機制,也可以系統生成。
    //alt + shift + s --> h 
    //右鍵 --> Source --> Generate hashCode() and equals()
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        long temp;
        temp = Double.doubleToLongBits(price);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Car other = (Car) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (Double.doubleToLongBits(price) != Double.doubleToLongBits(other.price))
            return false;
        return true;
    }
}