今天在学习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集合中的值也被删除了!
表达还是如此稀烂,看不懂的话大家自己跟进源码看看吧!!