关于HashMap,HashTable,HashSet浅析(博客园迁移)

 首先,最重要的,HashMap

 作为一个我们使用非常多的集合。最常被大家认知的是,它是一个key-value形式存储数据的数据结构,可以实现快速的存,取操作。
 关于HashMap的源码,我们截取一部分分析:
   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public  class  HashMap<K,V>
     extends  AbstractMap<K,V>
     implements  Map<K,V>, Cloneable, Serializable
{
 
     /**
     * The default initial capacity - MUST be a power of two.
     */
     static  final  int  DEFAULT_INITIAL_CAPACITY =  1  <<  4 // aka 16
 
     /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
     static  final  int  MAXIMUM_CAPACITY =  1  <<  30 ;
 
     /**
     * The load factor used when none specified in constructor.
     */
     static  final  float  DEFAULT_LOAD_FACTOR =  0 .75f;
 
     /**
     * An empty table instance to share when the table is not inflated.
     */
     static  final  Entry<?,?>[] EMPTY_TABLE = {};
 
     /**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */
     transient  Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

  

   我们看到了它实现的接口有Serializable,说明他能序列化,有Cloneable,说明能被克隆,有Map<K,V>,说明是一个Map(废话)。还有几条有用的信息:第一:有个默认初始容量,第二:有个最大容量,第三:有个调节因子,第四:有个数组。
   再往后看,发现这玩意又是由一个数组组成的,而这个数组的初始容量是16,最大容量是2^30。当然这个调节因子这个地方暂且不提。
   既然是用数组存储,我们存的又是Key-Value形式,这数组是怎么运作的呢?这里用往Map中添加数据为例说明:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public  V put(K key, V value) {
     if  (table == EMPTY_TABLE) {
         inflateTable(threshold);
     }
     if  (key ==  null )
         return  putForNullKey(value);
     int  hash = hash(key);
     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 ;
} 
   由于篇幅问题,我们就不粘贴太多代码了,先说一下,我们的hashMap实现是有一个数组实现,数组中存储的都是Entry<Key,Value>节点,Entry是HashMap的内部类,存储的是key,value,key的哈希值和下一个节点,具体可以自己查看源码。
  这里我们看到,首先,如果这个数字为空,则先初始化一个数组,如果要添加的key为空,直接进行空Key的添加(这里HashMap是允许有一个key为空的值的)。如果key不为空,则算出key的哈希值,根据哈希值,查找对应数组的位置,如果此key存在,就是说有相同的key,则覆盖(其实是链到后面的串,每个数组元素往后一个链表),没有则直接添加。这么一说其实就简单了,我们查询什么的就可以根据哈希值直接定位到相应的Entry,然后扔出来就是了。
 

然后我们说说HashSet:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
 
     // Dummy value to associate with an Object in the backing Map
     private  static  final  Object PRESENT =  new  Object();
 
     /**
     * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
     * default initial capacity (16) and load factor (0.75).
     */
     public  HashSet() {
         map =  new  HashMap<>();
     }

这里就可以看出,HashSet底层就是一个HashMap,而它跟HashMap不同的就是它是实现Set接口,所以他的数据必须唯一。

 最后是HashTable:

 由于篇幅问题,就不贴代码了,跟HashMap差不多,底层也是一个数组。就说一下它跟HashMap主要的区别吧:
 第一:HashMap允许一个null的key和任意value都有null,而HashTable无论key和value都不能为空。
 第二:HashTable可以看做是线程安全的HashMap。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值