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.
精彩评论