简单分析Java的HashMap.entrySet()的实现
2014-06-16 13:37
323 查看
关于Java的
Returns a Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
本文通过源码简单分析这一功能的实现。
首先要简单介绍一下HashMap的内部存储。我们知道,Map是用来存储key-value类型数据的,一个<k, v>对在Map的接口定义中被定义为Entry,HashMap内部实现了
当put一个新元素的时候,根据key的hash值计算出对应的数组下标。数组的每个元素是一个链表的头指针,用来存储具有相同下标的Entry。
主要看一下这个Set的
第一个
总结一下,HashMap的
p.s. 从这一点也可以看出为什么
HashMap.entrySet(),文档是这样描述的:这个方法返回一个Set,这个Set是HashMap的视图,对Map的操作会在Set上反映出来,反过来也是。原文是
Returns a Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
本文通过源码简单分析这一功能的实现。
首先要简单介绍一下HashMap的内部存储。我们知道,Map是用来存储key-value类型数据的,一个<k, v>对在Map的接口定义中被定义为Entry,HashMap内部实现了
Entry接口。HashMap内部维护一个
Entry数组。
transient Entry[] table;
当put一个新元素的时候,根据key的hash值计算出对应的数组下标。数组的每个元素是一个链表的头指针,用来存储具有相同下标的Entry。
Entry[] table +---+ | 0 | -> entry_0_0 -> entry_0_1 -> null +---+ | 1 | -> null +---+ | | ... |n-1| -> entry_n-1_0 -> null +---+
entrySet()方法返回的是一个特殊的Set,定义为HashMap的内部私有类
private final class EntrySet extends AbstractSet<Map.Entry<K,V>>
主要看一下这个Set的
iterator()方法。这个方法很简单,返回一个
EntryIterator类型的实例。
EntryIterator类型是泛型
HashIterator<T>的一个子类,这个类的内容很简单,唯一的代码是在
next()函数中调用了
HashIterator的
nextEntry()方法。所以,重点就变成了分析
nextEntry()方法。上述过程见下面的图示
HashMap |- table <------------------------------------\ \+ entrySet() |iterates | HashMap.HashIterator<T> | |returns ^ \- nextEntry() V - ^ HashMap.EntrySet | | \- iterator() |extends | | | | | instantiats | |calls \----------> HashMap.EntryIterator | \- next() /
HashIterator通过遍历
table数组,实现对HashMap的遍历。内部维护几个变量:
index记录当前在
table数组中的下标,
current用来记录当前在
table[index]这个链表中的位置,
next指向current的下一个元素。
nextEntry()的完整代码如下:
final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if ((next = e.next) == null) { Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; }
第一个
if用来判断在多线程的情况下是否出现并发错误,这里暂时不讨论。如果
next不是
null,那么返回并更新
next。更新方法是第三个
if的内容:如果当前链表还没有结束,则简单的把
next向后移一个;否则在
table中查找下一个非空的slot。
总结一下,HashMap的
entrySet()方法返回一个特殊的Set,这个Set使用
EntryIterator遍历,而这个Iterator则直接操作于HashMap的内部存储结构
table上。通过这种方式实现了“视图”的功能。整个过程不需要任何辅助存储空间。
p.s. 从这一点也可以看出为什么
entrySet()是遍历HashMap最高效的方法,原因很简单,因为这种方式和HashMap内部的存储方式是一致的。
相关文章推荐
- Java中集合框架,Collection接口、Set接口、List接口、Map接口,已经常用的它们的实现类,简单的JDK源码分析底层实现
- HashMap之entrySet( )底层实现原理分析
- Java中集合框架,Collection接口、Set接口、List接口、Map接口,已经常用的它们的实现类,简单的JDK源码分析底层实现
- java几种排序算法的实现及简单分析
- Java集合之HashMap源码实现分析
- Java学习资料-HashMap实现原理分析
- 哈希表(HashMap)分析及实现(JAVA)
- 利用JAVA的动态属性之反射原理实现一个简单AOP容器 - AOP的实现原理分析
- 哈希表(HashMap)分析及实现(JAVA)
- 哈希表(HashMap)分析及实现(JAVA)
- 哈希表(HashMap)分析及实现(JAVA)
- Java中Set集合的遍历及实现类比较分析
- java hashMap 简单使用以及深度分析
- [转]Java HashMap实现原理与源码分析
- Java中各Set实现类的性能分析
- Java HashMap实现原理分析
- 简单排序的Java实现与效率分析
- JAVA实现简单系统登陆注册模块的设计(附详细代码分析)
- java 散列与散列码探讨 ,简单HashMap实现散列映射表执行各种操作示列
- Java 内部类实现原理简单分析