map集合
来源:互联网 发布:淘宝联盟怎么微信推广 编辑:程序博客网 时间:2024/06/03 19:14
HashMap 实现类
构造方法源码:
put方法源码: eg: map.put("a","abc");
addEntry()方法源码:
由于元素的位置是通过hashcode取模数组长度而得, 现在由于需要扩容,数组长度会发生变化,
所以会在resize方法跟transfer方法中进行元素位置的重新分配。
resize()方法源码: // 重新计算数组长度
transfer()方法源码:// 重新分配
get方法源码
- public V get(Object key) {
- if (key == null)
- return getForNullKey();
- int hash = hash(key.hashCode()); // 还是计算key的hashcode,
- // 定位hash值在table数组中的索引,并通过equals方法定位元素在链表中的位置。
- for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
- Object k;
- if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
- return e.value;
- }
- return null;
- }
1、Entry[]数组是HashMap类的核心结构,称为“位桶数组”,键值对(key,value)就存储在这个数组里面。put元素的时候,首先对key的hashCode值作hash运算,即高16位不变,低16位与高16位异或(这么做是为了低位不变,高位变化的情况下发生冲突),然后再和位桶数组长度减一作与运算,从而定位元素在Entry数组中的索引。如果当前索引有元素,就通过hash值和equals方法与当前索引处的链表元素一一比较(若hash值相同并且equals也相同的key,把value旧值用新值替换掉),最后将元素存进当前链表的头部位置。JDK8中,若链表长度大于8,则采用红黑数结构。如果当前索引处没有元素,直接添加。如果元素个数超过阈值,对位桶数组进行扩容(不需要重新计算各个元素hash值,只需要看看原来hash值新增的二进制位是0还是1。如果是0,索引保持不变,如果是1,索引+原来位桶数组长度)。get元素的时候,同样地首先定位元素在Entry数组中的索引,然后通过hash值和equals方法定位元素在链表中的位置,取出该元素。
2、位桶数组的长度总是2的n次方,这样做的好处是:一、与运算相当于取模运算,但与运算效率要高于取模运算;二、(length-1)的二进制表示全为1,这样就会使得key的每一位都参与运算,从而元素在位桶数组中分布均匀,发生冲突概率也较小。
HashMap和HashTable区别:
继承的父类不同。
Hashtable 继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。
线程安全性不同。
Hashtable 中的方法是Synchronize的,而HashMap中的方法在缺省情况下是非Synchronize的。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步,但使用HashMap时就必须要自己增加同步处理。
key和value是否允许null值。
- 其中key和value都是对象,并且不能包含重复key,但可以包含重复的value。
- Hashtable中,key和value都不允许出现null值。
- HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应 的值为null。当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
- HashMap 通过
putForNullKey(value)
,将 null 键对应的值存在table[0]
的位置。
hash值不同
HashTable直接使用对象的hashCode,而HashMap需要重新计算hash值。
内部实现使用的数组初始化和扩容方式不同。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
TreeMap实现类
各Map实现类性能分析:
由于HashTable是一个线程安全的集合,因此HashMap通常要比HashTable快。
TreeMap通常比HashMap、HashTable慢,尤其插入、删除键值对时更慢。但是TreeMap中key-value对总是处于有序状态,无须专门进行排序操作。当TreeMap被填充后,就可以调用keySet(),取得key组成的Set,然后使用toArray()方法生成key的数组,接下来使用Arrays的binarySearch()方法查询对象。如果程序需要一个总是排好序的Map时,可以考虑使用TreeMap。
- Map 集合
- Map集合
- Map集合
- map集合
- Map集合
- map集合
- Map集合
- Map集合
- Map集合
- Map集合
- Map集合
- map集合
- Map集合
- Map集合
- Map集合
- Map集合
- Map集合
- Map集合
- 一个完整的android项目需要哪些标配
- JAVA第一课第二节知识点
- Android PathEffect 效果使用
- ZJU1037-Gridland
- Spark参数配置
- map集合
- MapReduce读写hbase
- Java设计模式——责任链模式
- WebService之CXF介绍
- ITIL 2011服务管理与认证读书笔记一——IT服务管理与ITIL
- 找朋友
- 顺序查找法
- drools 嵌套对象的处理
- ThreadLocal