1. 程式人生 > >java基礎類庫學習(二.2)Set子介面的實現類

java基礎類庫學習(二.2)Set子介面的實現類

Set子介面的實現類:HashSet/LinkedHashSet/TreeSet/EnumSet/SortedSet

Set子介面和Collection父介面原始碼對比?

1Collection父介面原始碼

 

public interface Collection<E> extends Iterable<E> {

int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
@since 1.8從jdk8開始介面支援有方法體,必須為static/default修飾
default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);
    boolean removed = false;
    final Iterator<E> each = iterator();
    while (each.hasNext()) {
        if (filter.test(each.next())) {
            each.remove();
            removed = true;
        }
    }
    return removed;
}
boolean retainAll(Collection<?> c);
void clear();
boolean equals(Object o);
int hashCode();
}


2Set子介面原始碼

 

public interface Set<E> extends Collection<E> {
int size();
boolean isEmpty();
Iterator<E> iterator();
Object[] toArray();
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean retainAll(Collection<?> c);
 
boolean removeAll(Collection<?> c);
void clear();
boolean equals(Object o);
int hashCode();

}

3結論

可以發現Set集合基本與Collection集合基本相同,只是Set集合不允許包含重複元素

Set子介面的實現類?HashSet

HashSet的說明

1HashSet實現類沒有實現執行緒同步,不支援多執行緒安全,需手動實現執行緒安全

2不能保證元素的順序,元素不重複

3hashSet原始碼

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{
    static final long serialVersionUID = -5024744406713321676L;

    private transient HashMap<E,Object> map;
public HashSet() {
    map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    addAll(c);
}
public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
public int size() {
    return map.size();
}
public boolean isEmpty() {
    return map.isEmpty();
}
public boolean contains(Object o) {
    return map.containsKey(o);
}
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
}
public void clear() {
    map.clear();
}
public Object clone() {
    try {
        HashSet<E> newSet = (HashSet<E>) super.clone();
        newSet.map = (HashMap<E, Object>) map.clone();
        return newSet;
    } catch (CloneNotSupportedException e) {
        throw new InternalError(e);
    }
}
private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException {
    // Write out any hidden serialization magic
    s.defaultWriteObject();

    // Write out HashMap capacity and load factor
    s.writeInt(map.capacity());
    s.writeFloat(map.loadFactor());

    // Write out size
    s.writeInt(map.size());

    // Write out all elements in the proper order.
    for (E e : map.keySet())
        s.writeObject(e);
}

}

注意到HashSet中並沒有重寫Object祖先類的hashCode()和equals()方法,但其父類 AbstractSet<E>實現了,因此用的就是 AbstractSet<E>的這兩個方法,

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {
public boolean equals(Object o) {
    if (o == this)
        return true;

    if (!(o instanceof Set))
        return false;
    Collection<?> c = (Collection<?>) o;
    if (c.size() != size())
        return false;
    try {
        return containsAll(c);
    } catch (ClassCastException unused)   {
        return false;
    } catch (NullPointerException unused) {
        return false;
    }
}
public int hashCode() {
    int h = 0;
    Iterator<E> i = iterator();
    while (i.hasNext()) {
        E obj = i.next();
        if (obj != null)
            h += obj.hashCode();
    }
    return h;
}

}

HashSet集合在執行add()操作時,判斷兩個元素是否相同的依據是euqals()和hashCode()方法,如果euqals()為true並且兩個物件的hashCode()也相等,那麼這兩個元素就是相等的,不會納入HashSet集合中