Java Set 源码分析

Java Set 源码分析

一、Set

HashSet:按照Hash算法来存储集合中的元素,有良好的存取和查找性能。
特点:1、无序;2、线程不同步3、集合元素值可以为null
使用equals()+hashCode()两个返回值都相等来判断两个元素是否相等。
如果hash冲突,HashSet会在同一位置使用链式结构来保存多个对象。

TreeSet:实现了SortSet()接口,采用的数据结构是红黑树。
最大的特点是有序(提供Comparable()接口支持自然排序和自定义排序)
当把一个对象加入TreeSet时,会调用compareTo()方法与容器中的元素比较,然后根据红黑树结构找到它的存储位置。

LinkedHashSet:与HashSet类似,使用元素的HashCode()值来存储元素。
不同点是同时使用了链表来维护元素的次序,当遍历元素时,LinkedHashSet将按照元素的添加顺序来访问集合。

二、HashSet

(1)HashSet继承自AbstractSet,实现了Set、Cloneable和Serializable接口。

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{

(2)内部实现:内部是用HashMap实现的。

public HashSet() {
        map = new HashMap<>();
    }

(3)构造函数:默认构造函数是new 一个HashMap。如果是传入Collections的构造函数,其大小为Collections的大小的1.3333倍。当然也可以直接传入int类型的初始容量大小。

public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

(4)add方法:调用的是map的put方法。

public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

三、TreeSet

(1)TreeSet实现了NavigableSet, Cloneable,和Serializable接口。其中,NavigableSet是扩展的 SortedSet,具有了为给定搜索目标报告最接近匹配项的导航方法。

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
{

(2)默认构造方法:底层实现是TreeMap

public TreeSet() {
this(new TreeMap

(3)add方法:直接调用的是TreeMap的put方法。TreeMap底层是用红黑树实现的,就是这个Entry,然后通过一个compare函数不断比较,小于就放左子树,大于就放右子树,如果重复就不入树,从而保证了数据的唯一。插入完毕后会调用一个fixAfterInsertion()方法,来调整红黑树,保持平衡。

public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
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;
    }

四、LinkedHashSet

(1)继承自HashSet,实现了Set, Cloneable,和Serializable接口。

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {

(2)默认构造函数:默认的容量是16,负载因子是0.75.

public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }

(3)LinkedHashSet的具体实现,通过super来看,是HashSet中的带参数的构造方法,具体实现的其实是LinkedHashMap

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值