开发者

Java - HashSet best way to implement iterator that does not support remove()

开发者 https://www.devze.com 2023-01-04 12:16 出处:网络
I have a class which uses a HashSet and I want the class implement Iterable, I do not, however, want the class iterator to support the remove() method.

I have a class which uses a HashSet and I want the class implement Iterable, I do not, however, want the class iterator to support the remove() method.

The default iterator of HashSet is HashSet.KeyIterator which is a private class within the HashSet class, so I cannot simply extend it and override the remove method.

Ideally I would like to avoid writing a wrapper 开发者_开发问答class for KeyIterator, but I am at a loss as to how else I could easily and simply implement my own iterator in any other way.

Any ideas?

Cheers,

Pete


java.util.Collections.unmodifiableSet(myHashSet).iterator();


If you're using Apache Commons Collections, you can use org.apache.commons.collections.iterators.UnmodifiableIterator :

UnmodifiableIterator.decorate(set.iterator());

Guava (Google Collections) also has an UnmodifiableIterator, which supports generics: com.google.common.collect.UnmodifiableIterator<E> Usage:

Iterators.unmodifiableIterator(set.iterator());


Below is one way that we can avoid those kind of exceptions while removing elements from the iterator

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);

This kind of implementations is guarantee that no exceptions at modifying iterator


Use the Composite pattern: create a new implementation of the Iterator interface that is a wrapper around the iterator from the HashSet, but instead of passing through calls to remove throw an UnsupportedOperationException.


Creating the wrapper using an anonymous inner class is fairly simple:

See this example:

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 );
        }

    }
}

You may also throw UnsupportedOperationException if you want to explicitly declare that the operation is not supported, but It may be a little excessive.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号