2010-06-18 9 views
6

J'ai une classe qui utilise un HashSet et je veux que la classe implémente Iterable, mais je ne veux pas, cependant, que l'itérateur de classe supporte la méthode remove().Java - HashSet meilleure façon d'implémenter itérateur qui ne supporte pas remove()

L'itérateur par défaut de HashSet est HashSet.KeyIterator qui est une classe privée dans la classe HashSet, donc je ne peux pas simplement l'étendre et redéfinir la méthode remove.

Idéalement, je voudrais éviter d'écrire une classe wrapper pour KeyIterator, mais je ne sais pas comment je pourrais facilement et simplement implémenter mon propre itérateur d'une autre manière.

Des idées?

Cheers,

Pete

+0

Est-ce que votre HashSet doivent être modifiable? –

+0

@Kevin Oui mais il doit aussi maintenir un nombre cohérent d'éléments, ce qui est géré par la logique interne de la classe mais pas quelque chose que je voudrais laisser en confiance si le HashSet est modifié en utilisant l'itérateur. – Peter

+0

Quel est le problème d'un wrapper? – whiskeysierra

Répondre

16
java.util.Collections.unmodifiableSet(myHashSet).iterator(); 
+4

Sachez simplement que l'itérateur renverra un 'UnsupportedOperationException' si vous essayez de le modifier. – Powerlord

+0

Quoi d'autre que faire? –

+0

Droite. Si vous voulez un itérateur qui ignore silencieusement les appels à remove(), vous devrez choisir l'une des autres solutions. –

1

Si vous utilisez Apache Commons Collections, vous pouvez utiliser org.apache.commons.collections.iterators.UnmodifiableIterator :

UnmodifiableIterator.decorate(set.iterator()); 

Goyave (Google Collections) a également un UnmodifiableIterator, qui supports génériques: com.google.common.collect.UnmodifiableIterator<E> Utilisation:

Iterators.unmodifiableIterator(set.iterator()); 
+0

Notez que les collections Apache ne supportent pas les génériques. –

+0

Mais il fournit un bon exemple, comment mettre en œuvre quelque chose comme ça ... :-) –

+2

...ou vous pouvez regarder 'com.google.common.collect.UnmodifiableIterator ' –

-1

Utilisez le Composite pattern: créer une nouvelle implémentation de l'interface Iterator qui est une enveloppe autour de la iterator du HashSet, mais au lieu de passer par des appels à remove jeter un UnsupportedOperationException.

+0

Une réponse valide, mais j'ai explicitement demandé une solution alternative. – Peter

+0

@Peter Vous avez raison. Je manque apparemment à la compréhension de la lecture. –

0

Création de l'emballage en utilisant une classe interne anonyme est assez simple:

Voir cet exemple:

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

    } 
} 

Vous pouvez également jeter UnsupportedOperationException si vous voulez déclarer explicitement que l'opération ne soit pas pris en charge, mais C'est peut-être un peu excessif.

1

ci-dessous est une façon que nous pouvons éviter ce genre d'exceptions tout en supprimant les éléments du 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); 

Ce genre de mise en oeuvre est garantie qu'aucune exception à la modification iterator

Questions connexes