IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Iterator - empêcher remove


Sujet :

avec Java

  1. #1
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Février 2012
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Février 2012
    Messages : 21
    Points : 18
    Points
    18
    Par défaut Iterator - empêcher remove
    Bonjour,

    Je me remets au java. Je suis un peu rouillé, j'ai pas pratiqué depuis un moment. Je suis un peu gêné sur un problème d'iterateur.

    En effet, le but serait d'empêcher le remove avec l'iterateur via une exception. Je ne vois pas trop comment faire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    public class MaClasse {
     
      private List<SubscriberI> souscripteurs;
     
     
     
      public MaClasse (){
       this.souscripteurs     = new LinkedList<SubscriberI>();
     }
    //.....
     
    // Parcours, sans retrait possible, retourne un iterateur 
     public Iterator<Topic> iterator(){
        Iterator it = souscripteurs.iterator();
    // ici 
       return it;
    }
    Je pensais faire quelque chose dans l'esprit de "Si appel de remove alors Exception". Mais comment faire ?

    Merci d'avance

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Il te faut pour cela encapsuler l'itérateur sur lequel tu veux itérer dans un itérateur où tu empêche le remove().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class DenyRemoveIterator<T> implements Iterator<T> {
     
    	private final Iterator<T> iterator;
     
    	public DenyRemoveIterator(Iterator<T> iterator) {
    		this.iterator=iterator;
    	}
     
    	@Override
    	public final boolean hasNext() {
    		return iterator.hasNext();
    	}
     
    	@Override
    	public final T next() {
    		return iterator.next();
    	}
     
    	/* en Java8 cette méthode est déjà implémenté comme ça en défault method, 
    	 * mais en Java7, il faut la mettre explicitement (donc décommenter)
             * Tu peux la décommenter en Java8 bien sûr, si tu veux
    	@Override
    	public final void remove() {
    		throw new UnsupportedOperationException();
    	}
    	 */
     
    }
    Et tu modifies ta classe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class MaClasse {
     
      private List<SubscriberI> souscripteurs;
     
     
     
      public MaClasse (){
       this.souscripteurs     = new LinkedList<SubscriberI>();
     }
    //.....
     
    // Parcours, sans retrait possible, retourne un iterateur 
     public Iterator<Topic> iterator(){
        Iterator it = souscripteurs.iterator();
       return new DenyRemoveIterator<>(it);
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Ou alors un truc tout con :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public Iterator<Topic> iterator(){
      return Collections.unmodifiableCollection(souscripteurs).iterator();
    }
    Ça fera que UnsupportedOperationException, on peut pas choisir, mais ça marche et c'est facile.

    Encore une autre possibilité, depuis Java 1.8, renvoyer un Stream au lieu d'un Iterator. Les Stream sont en lecture seule, ils n'exposent rien pour faire des modifications :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public Stream<Topic> stream(){
      return souscripteurs.stream();
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Février 2012
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Février 2012
    Messages : 21
    Points : 18
    Points
    18
    Par défaut
    J'étais pas loin, c'est rassurant, je pensais faire un truc de la sorte mais je voyais pas comment y parvenir.

    Je suis confronté à un autre petit souci, j'ai une erreur de cast.

    Le but de tout ça, c'est de permettre aux abonnés ayant souscrit à un type d’événements, d’être prévenus lorsque ceux-ci se produisent. Un médiateur se charge de l’inscription des abonnés aux différents thèmes de souscription et assure la notification des évènements.

    J'ai donc un ensemble de classes (je ne mets pas les interfaces) : Subscriber, Topic (abstraite), Mediator.

    La classe Subscriber :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public abstract class Subscriber implements SubscriberI {
      private   Topic topic;     // thème souscrit
      private   int priority;    // priorité du souscripteur
      private   boolean aborted; // arrêt de la notification
     
      public Subscriber(Topic topic){
        this.topic = topic;
      }
     
     //...
    }
    La classe Mediator :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    public class Mediator implements MediatorI{
     
      private List<SubscriberI> subscribers;
      private List<SubscriberI> deadSubscribers;
     
     
      public Mediator(){
       this.subscribers     = new LinkedList<SubscriberI>();
       this.deadSubscribers = new LinkedList<SubscriberI>();
      }
     
     
      public Mediator add(SubscriberI subscriber) throws Exception{
       //...fonctionne
      }
     
     
      public Mediator remove(SubscriberI subscriber) throws Exception{
       //..ok aussi
      }
     
     
      /** Obtention des souscripteurs à un thème.
       *  @param topic le thème souscrit
       *  @return la liste souscripteurs à ce thème, null si ce thème n’existe pas
       */
      public List<SubscriberI> getSubscribers(Topic topic){
         //...ok
      }
     
      //...
     
      }
     
       /** Obtention de tous les souscripteurs à un thème.
       *  @param topic le thème de publication
       *  @return la liste souscripteurs à ce thème, null si ce thème n’existe pas
       */
      public Iterator<Topic> iterator(){
       Iterator it = subscribers.iterator ();
     
        return new RemoveIterator<Topic>(it);
      }
     
     
     
      public static class RemoveIterator <T> implements Iterator<T> {
     
        public final Iterator<T> iterator;
     
        public RemoveIterator(Iterator<T> iterator) {
    		this.iterator=iterator;
        }
     
        @Override
    	public final boolean hasNext() {
    		return iterator.hasNext();
    	}
     
    	@Override
    	public final T next() {
    		return iterator.next();
    	}
     
     
    	public final void remove() {
    		throw new UnsupportedOperationException();
     
      }
    }
     
     
    }
    Le jeu de tests est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    protected void setUp(){
     	  this.mediator = new Mediator();
    	  this.planif = new Planif(); //Planif herite de Topic
    		this.s1 = new Sub("s1", planif);
                 //...d'autres
    		this.meteo = new Meteo(); //herite de Topic
    	  this.s6 = new Sub("s6", meteo);
    		this.s7 = new Sub("s7", meteo);
      }
     
    public void testIterator() throws Exception{
    	  mediator.add(s1).add(s6); // deux thèmes, deux abonnés 
      	Iterator<Topic> it = mediator.iterator();
        Topic t1 = it.next(); // ici que ça coince 
        assertTrue(" topic ?", t1.equals(planif) || t1.equals(meteo)); 
        Topic t2 = it.next();
        assertTrue(" topic ?", t2.equals(planif) || t2.equals(meteo));
        try{
          it = mediator.iterator();
          it.next();
          it.remove();
    J'ai l'erreur suivante : TestPublishSubscribe$Sub cannot be cast to Topic

  5. #5
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     private List<SubscriberI> subscribers;
    ...
     public Iterator<Topic> iterator(){
       Iterator it = subscribers.iterator ();
     
        return new RemoveIterator<Topic>(it);
      }
    it est un itérateur sur une liste typée SubstriberI, mais tu ne mets pas de type paramétré au type Iterator, ce qui te permet de la passer au constructeur.Tu peux le faire : mais tu as un warning qui te dit qu'il risque d'y avoir un problème de compatibilité de type, et c'est bien le cas au moment de l'appel de next(), car il y a une instance de TestPublishSubscribe.Sub (à priori le type de s1) qu'on essaye de mettre dans une variable de type Topic : donc un cast d'une classe vers une autre non compatible, d'où exception de casting.

    Si tu utilises des types paramétrés, il faut les utiliser dans toute la chaîne, ce qui permet d'éviter d'avoir ce genre de problème (au moins d'être averti par le compilateur).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     public Iterator<Topic> iterator(){
       Iterator<Topic> it = subscribers.iterator ();
     
        return new RemoveIterator<Topic>(it);
      }
    Tu aurais eu une erreur de compilation à la première ligne de la méthode.

    Sinon il faut faire attention à ce qu'on fait et ne pas caster un Truc en un Machin pas compatible.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  6. #6
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Février 2012
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Février 2012
    Messages : 21
    Points : 18
    Points
    18
    Par défaut
    L'idée serait donc de générer une liste des topics suivis par les souscripteurs, de coller un iterateur sur cette liste en empêchant le remove, donc ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
         //ajout nouvelle méthode
        public List<Topic> LesTopics(){
        Iterator<SubscriberI> it = subscribers.iterator();
        List<Topic> topics = new LinkedList<Topic>();
     
     
     
       while (it.hasNext()){
        SubscriberI souscripteur = it.next();
        topics.add(souscripteur.getTopic());
        }
        return topics;
        }
    Mais comment récupérer cette liste dans la classe interne ? Quand je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
       //dans ma classe interne RemoveIterator 
       public RemoveIterator() {
     
    		this.iter=LesTopics().iterator();
        }
    je me retrouve avec une erreur à la compilation ? Je tâtonne un peu, désolé.

  7. #7
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Comme ça, par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class Subscriber {
     
    	private final List<Topic> topics=new ArrayList<>();
     
    	public void addTopic(Topic topic) {
    		topics.add(topic);
    	}
     
    	public List<Topic> getTopics() {
    		return Collections.unmodifiableList(topics);
    	}
     
    	public Iterator<Topic> iterator() {
    		return topics.stream().iterator();
    	}
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Février 2012
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Février 2012
    Messages : 21
    Points : 18
    Points
    18
    Par défaut
    Merci à vous deux. Je n'ai plus d'erreur et j'obtiens des résultats cohérents. J'ai encore quelques questions, mais j'ai pas envie d'embêter.

  9. #9
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Pose tes questions ! Si ça nous embête on répondra pas. Mais, c'est peu probable !

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Février 2012
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Février 2012
    Messages : 21
    Points : 18
    Points
    18
    Par défaut
    Merci pour les réponses. D'autres questions viendront si besoin au fur et à mesure

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Iteration VS recursivité
    Par yacinechaouche dans le forum C
    Réponses: 40
    Dernier message: 16/11/2012, 11h52
  2. Empécher la sélection du texte des pages dans un WebBrowser
    Par DevelOpeR13 dans le forum Web & réseau
    Réponses: 2
    Dernier message: 05/06/2003, 18h36
  3. [debutant]iterator
    Par Wis dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 05/05/2003, 10h49
  4. vInt::iterator
    Par Monstros Velu dans le forum C++
    Réponses: 19
    Dernier message: 05/04/2003, 15h06
  5. [MSXML] Comment empécher la conversion des entités ?
    Par nima dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 08/11/2002, 14h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo