【问题标题】:Java - HashSet best way to implement iterator that does not support remove()Java - HashSet 实现不支持 remove() 的迭代器的最佳方法
【发布时间】:2010-06-18 17:53:03
【问题描述】:

我有一个使用HashSet 的类,我希望该类实现Iterable,但是我不希望类迭代器支持remove() 方法。

HashSet 的默认迭代器是HashSet.KeyIterator,它是HashSet 类中的一个私有类,所以我不能简单地扩展它并覆盖remove 方法。

理想情况下,我希望避免为 KeyIterator 编写包装类,但我不知道如何以任何其他方式轻松简单地实现我自己的迭代器。

有什么想法吗?

干杯,

皮特

【问题讨论】:

  • 你的 HashSet 需要修改吗?
  • @Kevin 是的,但它还必须保持一致的元素数量,这由类的内部逻辑管理,但如果使用迭代器修改 HashSet,我不想让其信任。
  • 包装器有什么不好?

标签: java collections iterator


【解决方案1】:
java.util.Collections.unmodifiableSet(myHashSet).iterator();

【讨论】:

  • 请注意,如果您尝试通过它修改 Set,迭代器将返回抛出 UnsupportedOperationException
  • 对。如果您想要一个静默忽略 remove() 调用的迭代器,则必须采用其他解决方案之一。
  • 要记住的一点是Collections.unmodifiableSet() 是一个薄包装。直接对 myHashSet 的更改仍将反映在不可修改的集合中。
【解决方案2】:

如果您使用的是 Apache Commons Collections,您可以使用org.apache.commons.collections.iterators.UnmodifiableIterator

UnmodifiableIterator.decorate(set.iterator());

Guava (Google Collections) 还有一个 UnmodifiableIterator,它支持泛型:com.google.common.collect.UnmodifiableIterator<E> 用法:

Iterators.unmodifiableIterator(set.iterator());

【讨论】:

  • 注意,apache 集合不支持泛型。
  • 但它提供了一个很好的例子,如何实现类似的东西...... :-)
  • ...或者你可以看看com.google.common.collect.UnmodifiableIterator<E>
【解决方案3】:

下面是我们在从迭代器中删除元素时避免此类异常的一种方法

List<String> results=new ArrayList<String>() //a collection
Iterator<String> itr=results.iterator();
List<String> toBeRemoved=new ArrayList<String>();

while(itr.hasNext()){
   if(condiation){
      tobeRemoved.add(itr.next);

     }
}
//now we can remove unnecessary elements form the iterator
results.removeAll(toBeRemoved);

这种实现是保证修改迭代器没有异常

【讨论】:

    【解决方案4】:

    使用Composite pattern:创建Iterator 接口的新实现,它是HashSet 中迭代器的包装器,但不是通过对remove 的调用,而是抛出UnsupportedOperationException

    【讨论】:

    • 一个有效的答案,但我明确要求提供替代解决方案。
    • @Peter 你是对的。我显然在阅读理解方面失败了。
    【解决方案5】:

    使用匿名内部类创建包装器相当简单:

    看这个例子:

    package some;
    import java.util.Set;
    import java.util.HashSet;
    import java.util.Iterator;
    
    class MyIterable<E> implements Iterable<E> {
        private Set<E> internalSet = new HashSet<E>();
    
        public MyIterable( E ... all ) {
            for( E e : all ){
                internalSet.add( e );
            }
        }
    
        public Iterator<E> iterator() {
            final Iterator<E> i = internalSet.iterator();
            return new Iterator<E>() {
                public boolean hasNext(){
                    return i.hasNext();
                }
                public E next(){
                    return i.next();
                }
                public void remove(){
                    //you may throw new UnsupportedOperationException();
                }
            };
        }
    
        // Test it
        public static void main( String [] args ) {
            Iterable<String> iterable = new MyIterable<String>("a", "b", "a", "b");
    
            System.out.println("Trying to invoke: remove");
            for(Iterator<String> iterator = iterable.iterator();
                                            iterator.hasNext();
                                            iterator.remove() ){
                    System.out.println(iterator.next());
            }
            System.out.println("Used in foreach");
            for( String s : iterable ){
                System.out.println( s );
            }
    
        }
    }
    

    如果要明确声明不支持该操作,也可以抛出UnsupportedOperationException,但可能有点过分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-05
      • 1970-01-01
      相关资源
      最近更新 更多