打字猴:1.700445199e+09
1700445199 }
1700445200
1700445201 }
1700445202
1700445203 同样的程序,只是把HashMap修改成了List,增加的字符串元素也相同(只是HashMap将其拆分成了两个字符串,一个是key,一个是value,此处则是把两个字符串放到list中),我们来看运行结果:
1700445204
1700445205 最大可用内存:63M
1700445206
1700445207 对内存大小:63M
1700445208
1700445209 空闲内存:11M
1700445210
1700445211 ArrayList运行很正常,没有出现内存溢出情况。两个容器,容纳的元素相同,数量相同,ArrayList没有溢出,但HashMap却溢出了。很明显,这与HashMap内部的处理机制有极大的关系。
1700445212
1700445213 HashMap在底层也是以数组方式保存元素的,其中每一个键值对就是一个元素,也就是说HashMap把键值对封装成了一个Entry对象,然后再把Entry放到了数组中,我们简单看一下Entry类:
1700445214
1700445215 static class Entry<K, V>implements Map.Entry<K, V>{
1700445216
1700445217 //键
1700445218
1700445219 final K key;
1700445220
1700445221 //值
1700445222
1700445223 V value;
1700445224
1700445225 //相同哈希码的下一个元素
1700445226
1700445227 Entry<K, V>next;
1700445228
1700445229 final int hash;
1700445230
1700445231 /*key、value的getter/setter方法,以及重写的equals、hashCode、toString方法*/
1700445232
1700445233 }
1700445234
1700445235 }
1700445236
1700445237 HashMap底层的数组变量名叫table,它是Entry类型的数组,保存的是一个一个的键值对(在我们的例子中Entry是由两个String类型组成的)。再回过头来想想,对我们的例子来说,HashMap比ArrayList多了一次封装,把String类型的键值对转换成Entry对象后再放入数组,这就多了40万个对象,这应该是问题产生的第一个原因。
1700445238
1700445239 我们知道HashMap的长度也是可以动态增加的,它的扩容机制与ArrayList稍有不同,其代码如下:
1700445240
1700445241 if(size++>=threshold)
1700445242
1700445243 resize(2*table.length);
1700445244
1700445245 在插入键值对时,会做长度校验,如果大于或等于阀值(threshold变量),则数组长度增大一倍。不过,默认的阀值是多大的呢?默认是当前长度与加载因子的乘积。
1700445246
1700445247 threshold=(int)(newCapacity*loadFactor);
1700445248
[ 上一页 ]  [ :1.700445199e+09 ]  [ 下一页 ]