Java - HashSet лучший способ реализовать итератор, который не поддерживает remove () - PullRequest
6 голосов
/ 18 июня 2010

У меня есть класс, который использует HashSet, и я хочу, чтобы класс реализовал Iterable, однако я не хочу, чтобы итератор класса поддерживал метод remove().

Итератор по умолчанию HashSet - это HashSet.KeyIterator, который является закрытым классом в классе HashSet, поэтому я не могу просто расширить его и переопределить метод удаления.

В идеале я хотел бы избежать написания класса-оболочки для KeyIterator, но я не знаю, как еще можно легко и просто реализовать свой собственный итератор любым другим способом.

Есть идеи?

Приветствия

Пит

Ответы [ 5 ]

16 голосов
/ 18 июня 2010
java.util.Collections.unmodifiableSet(myHashSet).iterator();
1 голос
/ 17 декабря 2010

Ниже приведен один из способов избежать подобных исключений при удалении элементов из итератора.

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

Этот вид реализации гарантирует отсутствие исключений при изменении итератора

1 голос
/ 18 июня 2010

Если вы используете коллекции Apache Commons, вы можете использовать org.apache.commons.collections.iterators.UnmodifiableIterator :

UnmodifiableIterator.decorate(set.iterator());

Гуава (Google Collections) также имеетUnmodifiableIterator, который поддерживает генерики: com.google.common.collect.UnmodifiableIterator<E> Использование:

Iterators.unmodifiableIterator(set.iterator());
0 голосов
/ 18 июня 2010

Создание оболочки с использованием анонимного внутреннего класса довольно просто:

См. Этот пример:

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, если хотите явно объявить, что операция не поддерживается, но она может быть немного чрезмерной.

0 голосов
/ 18 июня 2010

Используйте Составной шаблон : создайте новую реализацию интерфейса Iterator, которая является оберткой вокруг итератора из HashSet, но вместо того, чтобы проходить через вызовы к remove, выбрасывать UnsupportedOperationException.

...