集合Set

本文主要內容:

(1)Set

(2)HashSet與TreeSet

集合:Collection(以value的形式存在)、Map(以key-value的形式存在)

- Set:無序、無重複

(1)無序:添加的順序與獲取的順序不一致(不是集合本身是否有序,Tree自然有序)
(2)無重複:添加的元素不能一致(如果出現重複的元素,只存第一個,不在存入)
(3)HashSet(HashMap—>數據存儲結構:哈希表:分爲開散列、閉散列)
這裏用的是開散列:數組+鏈表
(4)TreeSet(TreeMap—>數據存儲結構:搜索樹(中序有序))
(5)Set集合家族基本使用:(有標記的是HashSet的方法)
boolean=add(E e):如果指定的元素不存在,則將其指定的元素添加(!)
boolean=addAll(Collection<? extends E> c):將指定集合中的所有元素添加到此集合
boolean=contains(Object o):如果此集合包含指定的元素,則返回 true (!)
boolean=equals(Object o):將指定的對象與此集合進行比較以實現相等
int=hashCode():返回此集合的哈希碼值
boolean=isEmpty():如果此集合不包含元素,則返回 true (!)
Iterator=iterator():返回此集合中元素的迭代器(!)
boolean=remove(Object o):如果存在,則從該集合中刪除指定的元素(!)
int=size():返回此集合中的元素數(!)
Object[]=toArray():返回一個包含此集合中所有元素的數組

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}
//Set源碼中的add方法,實際上用的是Map中的put方法,且將它當做key傳入
//所以set無重複,map中的key是無重複的

(6)Set集合無重複的特性:
HashSet:無重複的原則有兩個方法同時起作用:equals、hashCode,默認比較的是兩個對象的地址,若第二個對象地址與之前的一致,不在存入,如果想要改變其比較的規則,可以重寫上述的兩個方法。

HashSet<String> set = new HashSet<>();
set.add(new String("張三"));
set.add(new String("張三"));
set.add(new String("張三"));
System.out.println(set.size());//1
//在Set中無重複體現在equals方法與hashCode方法,又因爲String類的hashCode
//計算方式是計算每個字符的code碼乘以31在求和,所以相當於在重複
HashSet<Person> pSet = new HashSet<>();
pSet.add(new Person("李四"));
pSet.add(new Person("李四"));
pSet.add(new Person("李四"));
System.out.println(pSet.size());//3
//Person類的hashCode方法是繼承於Object類中的方法,Object有獨有的方式來
//計算hashCode三個對象的hashCode值不一樣,所以不是重複
//綜上所述:如果想要使三個對象重複,可以通過覆寫equals與hashCode方法

TreeSet:無重複的原則只有一個方法起作用:compareTo,上述的方法不是每個對象都有的,若想將某一個對象存入TreeSet集合中,需要讓對象所屬的類實現接口Comparable,實現接口後將ComparatorTo方法重寫,返回int,負數靠前排布,正數排列靠後。(有序)

TreeSet<Person> set = new TreeSet<>();
set.add(new Person("張三"));
System.out.println(set);
//會產生異常,執行結果如下:
Exception in thread "main" java.lang.ClassCastException: bittech.Person cannot be cast to java.lang.Comparable
	at java.util.TreeMap.compare(TreeMap.java:1294)
	at java.util.TreeMap.put(TreeMap.java:538)
	at java.util.TreeSet.add(TreeSet.java:255)
//TreeSet源碼
public boolean add(E e) {
    return m.put(e, PRESENT)==null;
}
//TreeMap源碼
public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        compare(key, key); // type (and possibly null) check
        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    int cmp;
    Entry<K,V> parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    else {
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        do {
            parent = t;
            cmp = k.compareTo(t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    Entry<K,V> e = new Entry<>(key, value, parent);
    if (cmp < 0)
        parent.left = e;
    else
        parent.right = e;
    fixAfterInsertion(e);
    size++;
    modCount++;
    return null;
}

綜上所知:將某一個對象存入TreeSet集合中,需要讓對象所屬的類實現接口Comparable,實現接口後將ComparatorTo方法重寫
正解:

class Person implements Comparable<Person>{
    private String name;
    public Person(String name){
        this.name = name;
    }

    @Override
    public int compareTo(Person o) {
        return this.name.compareTo(o.name);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class Test2 {
    public static void main(String[] args) {
        TreeSet<Person> set = new TreeSet<>();
        set.add(new Person("張三"));
        System.out.println(set);
    }
}
//執行結果如下:
[Person{name='張三'}]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章