今天在学习nio的过程时,突然发现个小细节平时都没有注意到的,大家都知道Set接口中有一个iterator方法可以进行迭代,
不过估计很多人都没有太注意Iterator接口的remove方法,该方法将移除迭代器中最后一个元素(即当前迭代器指向的元素)。
那么我们在使用Set的iterator方法返回一个迭代器后,使用remove方法移除一个元素,原Set集合是否发生变化?
这只是写代码时的一个小细节,提醒还未注意到的朋友,已经了解的可以略过了。
接下来我们通过源码解决疑问。
先拿HashSet类来说:
该类实现了Set接口,维护一个HashMap对象,将set集合每一个元素作为map的key以保证集合中元素没有重复。
iterator方法实际返回map的keySet的迭代,需要注意的是该keySet不是HashSet类型的。
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator<E> iterator() {
return map.keySet().iterator();
}
跟进HashMap类中,HashMap则是维护一个Entry数组来保存键值对,
打开eclipse的outline视图,你会发现HashMap中很多的内部类,我们需要关心的是HashIterator类,
HashIterator类是一个抽象类,有另外三个类分别继承了它,这三个类是ValueIterator,KeyIterator和EntryIterator,大家看名字就应该了解各自的作用了
这三个类呢,都只重写了next方法来满足各自的需求,而我们关注的remove方法则在抽象类HashIterator中
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;
}
该方法只是获取当前的key值,然后交给HashMap的removeEntryForKey来处理
跟进去,一切明了
/**
* Removes and returns the entry associated with the specified key
* in the HashMap. Returns null if the HashMap contains no mapping
* for this key.
*/
final Entry<K,V> removeEntryForKey(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
int i = indexFor(hash, table.length);
Entry<K,V> prev = table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return e;
}
prev = e;
e = next;
}
return e;
}
总结:Set维护的是一个hashMap对象,iterator方法返回的是该hashMap对象的key集合的迭代(也就是HashMap$KeyIterator的对象),KeyIterator的remove方法由父类HashIterator实现,实际却是返回当前迭代的key值交与HashMap再做进一步处理,最终删除还是HashMap删除的,自然Set集合中的值也被删除了!
表达还是如此稀烂,看不懂的话大家自己跟进源码看看吧!!