HashMap从源码角度分析遍历过程
来源:互联网 发布:炉石毕游侠知乎 编辑:程序博客网 时间:2024/05/22 05:32
上一篇分析了HashMap的数据结构以及put方法的源码
HashMap源码解析,下面分析HashMap的遍历过程的源码。
遍历的方法有很多中,主要分析下面这种:
Iterator<Map.Entry<String, String>> iterator = hashMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> next = iterator.next(); String key = next.getKey(); String value = next.getValue(); }
hashMap.entrySet()会new一个EntrySet对象。
调用entrySet.iterator()方法时会通过newEntryIterator()方法调用HashIterator的构造方法创建一个Iterator实例。
public Set<Map.Entry<K,V>> entrySet() { return entrySet0();}private Set<Map.Entry<K,V>> entrySet0() { Set<Map.Entry<K,V>> es = entrySet; return es != null ? es : (entrySet = new EntrySet());}private final class EntrySet extends AbstractSet<Map.Entry<K,V>> { public Iterator<Map.Entry<K,V>> iterator() { return newEntryIterator(); } //.............. }Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator();private abstract class HashIterator<E> implements Iterator<E> { HashMapEntry<K,V> next; // next entry to return int expectedModCount; // For fast-fail int index; // current slot HashMapEntry<K,V> current; // current entry HashIterator() { expectedModCount = modCount; if (size > 0) { // advance to first entry HashMapEntry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } } public final boolean hasNext() { return next != null; } final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); HashMapEntry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if ((next = e.next) == null) { HashMapEntry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; } public void remove() { if (current == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); Object k = current.key; current = null; HashMap.this.removeEntryForKey(k); expectedModCount = modCount; } }
HashIterator的构造方法通过while循环遍历HashMap中的数组,找到第一个不为null的值,并赋值给next。
PS: HashMap中取数据是从数组的第0个位置开始找的,根据上篇分析put方法时,知道插入的位置时根据hash值计算出来的,所以HashMap取出数据的顺序和插入的顺序是不一致的。
HashIterator() { expectedModCount = modCount; if (size > 0) { // advance to first entry HashMapEntry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } }
通过hashMap.entrySet().iterator()已经找到了第一个不为null的元素,如果hasNext()返回false表示没有别的元素,返回true调用iterator.next()方法,此方法最终调用nextEntry()。
nextEntry将构造方法中找到的next返回,并通过next节点中存储的下一个节点的指针去找下个数据,如果下一个数据为null,则表示该链表已经到最尾部了,则继续查找数组下一个位置存储的链表,直到不为null,或者遍历结束。
public final boolean hasNext() { return next != null; } final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); //将next 赋值给e 当作返回值使用 HashMapEntry<K,V> e = next; if (e == null) throw new NoSuchElementException(); //链表结构存储了下个节点的指针,可以直接取 if ((next = e.next) == null) { //当前节点是链表中最后一个元素,从数组下一个位置中查找不为null的元素 HashMapEntry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; }
调用hashMap.get(“4”);取数据,流程和调用put方法保存数据相同,都是通过key的值得到hash值然后找到数组中的位置,之后遍历链表得到Entry。找到Entry之后调用getKey和getValue就非常简单了。
final Entry<K,V> getEntry(Object key) { if (size == 0) { return null; } int hash = (key == null) ? 0 : sun.misc.Hashing.singleWordWangJenkinsHash(key); for (HashMapEntry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; }
这里HashMap的遍历就分析完了。
- HashMap从源码角度分析遍历过程
- 从源码的角度分析Hashtable和HashMap的区别
- 从源码角度分析linearLayout测量过程以及weight机制
- 从源码角度分析view的layout过程
- 从源码角度分析view的draw过程
- 从源码的角度分析Volley加载数据的过程
- 从源码分析 HashMap
- 从源码角度解析HashMap特性
- 从源码角度分析ViewDragHelper
- 从源码角度分析NestedScrolling
- 从Java源码的角度来分析HashMap与HashTable的区别
- Java面试之从源码的角度分析Hashtable和HashMap
- for循坏遍历list过程中remove某个元素出错,从源码角度解释
- 从源码分析HashMap实现
- java中HashMap详解(从源码角度看内部实现)
- 从源码角度认识ArrayList,LinkedList与HashMap
- 从源码角度简析 Hashtable、HashMap 和 LinkedHashMap
- 从源码角度简要分析ActionBar框架
- RTSP协议分析
- java中HashMap排序中实现Comparator接口
- 数据库存储过程
- python下载及安装
- 怎样连接Redis数据库
- HashMap从源码角度分析遍历过程
- 项目拆分
- java多线程-基础概念
- 左神算法课-找出数组中出现次数超过一半的数及其进阶
- [LeetCode]26. Remove Duplicates from Sorted Array
- 99乘法表及杨辉三角C代码实现
- 网狐荣耀版游戏服务器出现"MDM_GF_GAME 游戏命令返回 false"
- 1009.说反话
- android:padding和android:layout_margin的区别