HashMap中通过keySet遍历的顺序
Posted hanzhengjie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HashMap中通过keySet遍历的顺序相关的知识,希望对你有一定的参考价值。
public Set<K> keySet() { Set<K> ks = keySet; if (ks == null) { ks = new KeySet(); keySet = ks; } return ks; } final class KeySet extends AbstractSet<K> { public final int size() { return size; } public final void clear() { HashMap.this.clear(); } public final Iterator<K> iterator() { return new KeyIterator(); } public final boolean contains(Object o) { return containsKey(o); } public final boolean remove(Object key) { return removeNode(hash(key), key, null, false, true) != null; } public final Spliterator<K> spliterator() { return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0); } public final void forEach(Consumer<? super K> action) { Node<K,V>[] tab; if (action == null) throw new NullPointerException(); if (size > 0 && (tab = table) != null) { int mc = modCount; for (int i = 0; i < tab.length; ++i) { for (Node<K,V> e = tab[i]; e != null; e = e.next) action.accept(e.key); } if (modCount != mc) throw new ConcurrentModificationException(); } } }
以上是HashMap中ketSet的方法,以及KeySet类的源码
当第一次调用keySet时会创建一个对象,当遍历时会创建KeyIterator对象;这个对象是一个hashmap内部类
final class KeyIterator extends HashIterator implements Iterator<K> { public final K next() { return nextNode().key; } }
继续调用HashIterator的nextNode()方法;HashIterator也是HashMap的内部类
abstract class HashIterator { Node<K,V> next; // next entry to return Node<K,V> current; // current entry int expectedModCount; // for fast-fail int index; // current slot //这里可以看出next方法是按照数组的index从小到大遍历的 HashIterator() { expectedModCount = modCount; Node<K,V>[] t = table;//存储node的数组; current = next = null; index = 0; if (t != null && size > 0) { // advance to first entry 为next节点赋值 do {} while (index < t.length && (next = t[index++]) == null); } } public final boolean hasNext() { return next != null; } final Node<K,V> nextNode() { Node<K,V>[] t; Node<K,V> e = next; if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (e == null) throw new NoSuchElementException(); if ((next = (current = e).next) == null && (t = table) != null) { do {} while (index < t.length && (next = t[index++]) == null); } return e; } public final void remove() { Node<K,V> p = current; if (p == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); current = null; K key = p.key; removeNode(hash(key), key, null, false, false); expectedModCount = modCount; } }
modCount != expectedModCount 这个判断的存在是为了不允许我们在遍历时通过hashmap的方法进行添加删除
modCount和expectedModCount 记录了map的修改次数
当通过haspmap修改时 HashIterator内部的expectedModCount 不会被修改;
以上是关于HashMap中通过keySet遍历的顺序的主要内容,如果未能解决你的问题,请参考以下文章