[Java] HashMap 源码简要分析

[Java] HashMap 源码简要分析

 特性

* 允许null作为key/value。
* 不保证按照插入的顺序输出。使用hash构造的映射一般来讲是无序的。
* 非线程安全。
* 内部原理与Hashtable类似。
 
源码简要分析
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public  class  HashMap<K,V>
{
      static  final  int  DEFAULT_INITIAL_CAPACITY =  16  // 默认初始容量是16。(必须是2的次方)
      static  final  int  MAXIMUM_CAPACITY =  1  <<  30  // 即2的30次方
      static  final  float  DEFAULT_LOAD_FACTOR =  0 .75f;  // 默认装载因子
 
      Entry[] table;   // Entry表
      int  size;  // Entry[]实际存储的Entry个数
      int  threshold;  // reash的阈值,=capacity * load factor
      final  float  loadFactor;
 
      // 构造函数
      public  HashMap( int  initialCapacity,  float  loadFactor) {
      // 找到一个比initialCapacity大的最小的2的次方数
      int  capacity =  1 ;
      while  (capacity < initialCapacity)
             capacity <<=  1 ;
      }
 
      this .loadFactor = loadFactor;
      threshold = ( int )(capacity * loadFactor);
      table =  new  Entry[capacity];
 
      // addEntry()
     void  addEntry( int  hash, K key, V value,  int  bucketIndex) {
         Entry<K,V> e = table[bucketIndex];
         table[bucketIndex] =  new  Entry<>(hash, key, value, e);
         if  (size++ >= threshold)
             resize( 2  * table.length);
     }
 
      // put():添加元素
      public  V put(K key, V value) {
           int  hash = hash(key.hashCode());      // key的hash值
           int  i = indexFor(hash,table.length);      // 槽位
 
           // 寻找是否已经有key存在,如果已经存在,使用新值覆盖旧值,返回旧值
           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;
                 return  oldValue;
             }
           }
 
           // 添加Entry
           addEntry(hash,key,value,i);
           return  null ;
      }
 
      // resize():重新哈希
     void  resize( int  newCapacity) {
         Entry[] oldTable = table;
         int  oldCapacity = oldTable.length;
         Entry[] newTable =  new  Entry[newCapacity];
         transfer(newTable);
         table = newTable;
         threshold = ( int )(newCapacity * loadFactor);
     }
 
     /**
      * Transfers all entries from current table to newTable.
      */
     void  transfer(Entry[] newTable) {
         Entry[] src = table;
         int  newCapacity = newTable.length;
         for  ( int  j =  0 ; j < src.length; j++) {
             Entry<K,V> e = src[j];
             if  (e !=  null ) {
                 src[j] =  null ;    
                 do  {
                     Entry<K,V> next = e.next;
                     int  i = indexFor(e.hash, newCapacity);
                     e.next = newTable[i];
                     newTable[i] = e;
                     e = next;
                 while  (e !=  null );
             }
         }
     }
 
}

  

遍历方式

* 低效遍历:按照Key进行遍历,则每次都需要按Key查找槽位(不同的Key有重复查找),且可能需要遍历槽位上所在Entry链表(不同的Key有重复遍历)。
* 高效遍历:HashMap的entrySet()返回自定义的EntryIterator,是先按照槽位遍历一次,再遍历一次槽位上Entry链表。
1
2
3
4
5
6
Map<String, String[]> paraMap =  new  HashMap<String, String[]>();
for ( Map.Entry<String, String[]> entry : paraMap.entrySet() )
{
     String appFieldDefId = entry.getKey();
     String[] values = entry.getValue();
}

  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值