HashSet与HashMap实现

1 篇文章 0 订阅
1 篇文章 0 订阅

1、通过查看源码,可以看到HashSet的无参构造函数:

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

其中map: private transient HashMap<E, Object> map;

由此我们可以推出:HashSet底层使用HashMap来实现的

但是我们知道Map是由key和value组成的键值对,而Set只有元素,他们是怎么联系起来的呢?

2、接下来我们看HashSet是怎么添加元素的

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

其中PRESENT:private static final Object PRESENT = new Object();

由于HashSet我们只需要key,不需要value,但是它又依靠Map来实现,我们就需要建立一个假的对象PRESENT(所有的value都是该对象)。

3、通过查看源码发现HashSet的add、remove、iterator、clear、isEmpty等方法都是调用map的方法来实现的。接下来我们就重点分析HashMap的底层实现

4、首先查看HashMap的构造函数:

public HashMap() {
       this.loadFactor = DEFAULT_LOAD_FACTOR;//负载因子,float类型,底层所维护的哈希表的负载因子;默认的负载因子0.75f赋值给它

threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);

table = new Entry[DEFAULT_INITIAL_CAPACITY];//table是一个长度为16的Entry类型的数组,由此可见HasnMap底层使用数组实现,但此时的数组不是简单的数组,是一个Entry类型的数组

init();//包级别的,外部无法访问
    }

5、Entry是什么呢?

Entry是一个内部类,其实现了Map.Entry

static class Entry<K,V> implements Map.Entry<K,V> 

{

 final K key;
        V value;
        Entry<K,V> next;
        int hash;


        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }

}

6、HashMap的put方法

public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);//其中hash是一个散列函数,他根据key的hashCode的来计算
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }


        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

总结:

1.HashMap底层维护一个数组,我们向HashMap中所放置的对象实际上是存储在该数组中

2.当向HashMap中put一对键值时,他会根据key的hashCode值计算出一个位置,该位置就是此对象准备往数组中存放的位置

3.如果该位置没有对象存在,就将此对象直接放入数组当中;如果该位置已经有对象存在了,则顺着此存在着的对象的链开始寻找(Entry类有一个Entry类型的next成员变量,指向了该对象的下一个对象),如果此链上有对象的话,再去使用equals方法进行比较,如果对此链上的某个对象的equals方法比较为false,则将该对象存放到数组当中,然后将数组中该位置上以前存在的那个对象链接到此对象的后面

HashMap的内存布局示意图:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值