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

Langage Java Discussion :

Vector et class


Sujet :

Langage Java

  1. #1
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut Vector et class
    Bonjour à tous, j'aimerais savoir comment savoir si un vector contient un certain type de class, exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Vector<Vehicule> v = new Vector<>();
    v.add(new Moto());
    v.add(new Voiture());
     
    if( v.contains( Moto.class ) ) // ?
    {
    ...
    }
    Merci de votre aide

  2. #2
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    if (v instanceof Moto)
    {
       ...
    }
     
    ou 
     
    if (v.getClass().equals(Moto.class))
    {
       ...
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut
    Hum.. je crois que tu n'as pas compris ce que je veux faire.
    Je veux chercher dans mon vecteur si il contient par exemple une classe Moto ou Avion donc si je fait v instanceof Moto je compare la class Vector à Moto non ?

    Actuellement je peux faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for( int i = 0; i < v.size(); i++ )
    {
        if(v.elementAt(i).getClass().equals(Moto.class)
        {
            ...
        }
    }
    Y a-t-il une fontion/methode pour faire cette recherche sans passé par des boucles ?

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    v.stream().anyMatch(Moto.class::isInstance)

  5. #5
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    v.stream().anyMatch(Moto.class::isInstance)
    Merci, ça fonctionne parfaitement

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Pour information c'est à peu près équivalent à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    boolean contientUneMoto(Collection<?> collection) {
      for(Object o : collection) {
        if(Moto.class.isInstance(o)) {
          return true;
        }
      }
      return false;
    }
    lui-même à peu près équivalent à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    boolean contientUneMoto(Collection<?> collection) {
      for(Object o : collection) {
        if(o instanceof Moto) {
          return true;
        }
      }
      return false;
    }
    Bref, une fois qu'on comprend à peu près comment répondre au problème, les streams et les lambdas, ou les références de méthodes dans le cas présent, viennent à la rescousse pour faire la même solution de manière plus compacte.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut
    Je savais déjà faire comme ci-dessus mais j'avais beaucoup de ligne pour pas grand choses donc je trouver ça un peu "moche" ->
    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
     
    public void render( Graphics g )
    	{
    		for(Entry<Long, Vector<Component>> entry : this.entities.entrySet()) 
    		{
    		    Vector<Component> components = entry.getValue();
     
    		    if( components.stream().anyMatch(CTexture.class::isInstance) 
    		    	&& components.stream().anyMatch(CPosition.class::isInstance) )
    		    {
    		    	double x = 0;
    		    	double y = 0;
     
    		    	for( Component c : components )
    		    	{
    		    		if( c instanceof CPosition )
    		    		{
    		    			x = ((CPosition) c).x();
    		    			y = ((CPosition) c).y();
    		    		}
    		    	}
     
    		    	for( Component c : components )
    		    	{
    		    		if( c instanceof CTexture )
    		    		{
    		    			g.drawImage(this.tl.texture(((CTexture) c).texture()).getScaledCopy(((CTexture) c).size().x(), ((CTexture) c).size().y()),(float)x,(float)y);
    		    		}
    		    	}
    		    }
    		}
    	}



    Aujourd'hui j'ai un autre problème qui dans le même genre, je souhaite éviter plusieurs instances d'une même classes dans un vecteur. J'ai une méthode qui permet de remplir mon vecteur et j'ai essayé d'y incorporer ce test.

    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 void attach( long id, Component c )
    	{
    		if( entities.containsKey(id) )
    		{
    			if( this.entities.get(id).stream().anyMatch(c.getClass()::isInstance)  )
    			{
    				for( int i = 0; i < this.entities.get(id).size(); i ++)
    				{
    					if( this.entities.get(id).elementAt(i).getClass().isInstance(c.getClass()) )
    					{
    						this.entities.get(id).remove(i);
    					}
    				}
    			}
    			this.entities.get(id).add(c);
    		}
    	}
    Bien-sur cela ne fonctionne pas et dans tout les cas je trouve que c'est un peu long pour un simple rechercher/remplacer. Je pensais pouvoir trouver une méthode de ce genre avec le stream de vector mais je trouve pas vraiment de tutoriel ou de doc claire (enfin si il y a la doc d'oracle mais quasi aucun exemple) :/

  8. #8
    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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Salut,

    Première question : pourquoi utiliser un Vector ? C'est une veille classe dont l'implémentation est basée sur le même principe que ArrayList, sauf quelle est synchronisée. Si tu les manipules par un seul thread, autant utilser une ArrayList, ce qui te simplifiera certains traitements par stream (Collectors.toList() versus Collectors.toCollection(Vector::new)) et tu gagneras en performances. Si les manipulations sont multithread, utiliser une ConcurrentLinkedQueue par exemple.

    Pour faire le traitement dont tu parles, tu ne dois pas supprimer si le vecteur contient un composant de la classe donnée, mais simplement ne pas ajouter, donc ça donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if( !this.entities.get(id).stream().anyMatch(c.getClass()::isInstance)  ) {
        this.entities.get(id).add(c);
    }
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if( this.entities.get(id).stream().noneMatch(c.getClass()::isInstance)  ) {
        this.entities.get(id).add(c);
    }
    Autrement, pour gérer par stream le dédoublonnage (on part du cas d'un vecteur qui contient plusieurs composants tels qu'ils soient de la classe de c, on pourrait procéder comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Collection<Component> distinctOnClassComponents = components.stream()
    				.collect(Collectors.groupingBy(c.getClass()::isInstance))
    				.entrySet().stream().flatMap(entry-> 
    						entry.getKey()
    				        ?Stream.of(entry.getValue().stream().findFirst().get())
    						:entry.getValue().stream())
    				.collect(Collectors.toList());
    		components.retainAll(distinctOnClassComponents);
    A noter que le isInstance teste si l'objet est de la classe de c, pas si sa classe est celle de c. Nuance. Si B extends A, et b=new B(), A.class.isInstance(b) est vrai. Pour qu'il ne soit vrai que si l'objet testé est de classe A, mais faux s'il est de classe B extends A, il faut utiliser l'égalité sur la classe. Dans ce cas, l'expression précédente devient plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Collection<Component> distinctOnClassComponents = components.stream()
    				.collect(Collectors.groupingBy(Object::getClass))
    				.values().stream().map(l->l.stream().findFirst().get())
    				.collect(Collectors.toList());
    Dernière remarque : pour faire exactement ce que ton code fait, au lieu de faire al boucle, tu aurais pu écrire tout simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.entities.get(id).removeIf(c.getClass()::isInstance)
    Bien sûr, ça supprime tous les composants tels qu'ils soient instance de la classe de c.
    On peut ensuite faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.entities.get(id).add(c);
    Et on se retrouve avec une collection de composants tels qu'un seul soit de la classe de c. Même pas besoin de faire le test "anyMatch" (et ne pas le faire gagne un parcours de collection).
    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.

  9. #9
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut
    Merci à toi pour cette grande réponse ! Alors pour ce qui en est de l'utilisation d'un vector c'est simplement parce que j'ai appris à faire un ECS en même temps que son application dans mon cadre et j'ai lu que les classe devais être immuable, car un ECS est généralement prévu pour du multithreading donc, le vector à suivi dans mon choix. Finalement pour mon jeu je n'ai pas d’intérêt à avoir plusieurs thread, mais par flemmardise manque de temps, je n'ai rien changé bien que je susse que je perds des performances...

    [...] tu ne dois pas supprimer si le vecteur contient un composant de la classe donnée, mais simplement ne pas ajouter [...]
    En fait, je dois supprimer l'ancien composant du vecteur avant d'en mettre un nouveau, mais j'avoue ne pas l'avoir clairement énoncé.
    Rechercher et remplacer voilà le but de cette méthode. Comme mes composants sont immuables si je veux modifier une valeur, je n'ai pas d'autre choix que de faire comme ça. Pour le moment, le jeu tourne sur un seul thread, mais je préfère garder mes composants immuables si jamais je souhaite, par la suite, utiliser plusieurs threads pour gérer par exemple la physique et la logique séparément.

  10. #10
    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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Disixlis Voir le message
    et j'ai lu que les classe devais être immuable
    ouais, m'enfin, un Vector n'a rien d'immuable.

    Citation Envoyé par Disixlis Voir le message
    En fait, je dois supprimer l'ancien composant du vecteur avant d'en mettre un nouveau, mais j'avoue ne pas l'avoir clairement énoncé.
    Rechercher et remplacer voilà le but de cette méthode.
    Un rechercher/remplacer par Stream n'est pas une bonne idée : un Stream ne doit pas modifier la source du Stream. Elle en produit un nouveau. Ce qui veut dire que tu serais obliger de recréer une instance de collection à chaque fois. C'est d'ailleurs le cas dans mon exemple avec retainAll.

    La solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    this.entities.get(id).removeIf(c.getClass()::isInstance)
    this.entities.get(id).add(c);
    correspond plus à ta demande. Mais n'est pas la plus optimisée : on supprime, donc on décale l'ensemble des composants situés à la suite vers la gauche (une copie de tableau inutile, puisqu'il suffirait de remplacer l'élément situé à l'index en question).
    On pourrait faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    		Optional<Component> old = components.stream().filter(c.getClass()::isInstance).findFirst();
    		if (old.isPresent() ) {
    			Collections.replaceAll(components, old.get(), c);
    		}
    		else {
    			components.add(c);
    		}
    Mais pas sûr que ça plus optimisé que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    		int index=-1;
    		for(int i=0; i<components.size(); i++) {
    			if ( c.getClass().isInstance(components.get(i)) ) {
    				index=i;
    				components.set(index, c);
    				break;
    			}
    		}
    		if ( index==-1 ) {
    			components.add(c);
    		}
    Si tu n'as pas héritage entre Component, on peut aussi utiliser une map :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		Map<Class<?>, Component> components = new HashMap<>();
    Pour ajouter ou remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    components.put(c.getClass(), c);
    Pour supprimer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    components.remove(c.getClass());
    Ou pour supprimer par type (sans avoir l'instance) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    components.remove(MyComponent.class);
    Pour parcourir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(Component component: components.values()) {
    }
    Cependant, dans le cadre d'un ECS, on a deux types de listes de Component : celle de l'Entity et celle du System. Si cette solution peut fonctionner pour celle de l'Entity, puisqu'une Entity est censé n'avoir qu'un composant de chaque type (et encore, on pourrait profiter du modèle objet pour avoir des composants abstraits, par exemple pour gérer les armes mutiples du joueur). En revanche, celle d'un System va contenir forcément plusieurs composants de même classe (c'est sa fonction). Et du coup, ça ne fonctionne pas du tout.

    Je ne sais pas ce que dit l'état de l'art des ECS, mais à mon avis il est bien plus simple de gérer des composants mutables, dans le cadre d'une boucle évenementielle (un thread unique de traitement, synchronisé sur l'EDT). Dans un ECS, on peut gérer un thread par System. Normalement, le modèle devrait interdire le partage de composants par deux systèmes. Mais j'imagine qu'on doit pouvoir trouver des composants qu'on pourrait partager entre System. Dans ce cas, on pourrait utiliser des SystemManager qui aurait un seul thread pour gérer un ensemble de Systems. Mais avec ce système, il est compliqué de gérer la synchro avec l'EDT, et on peut facilement introduire des saccades dans l'animation de l'UI.
    Une solution pourrait être de gérer les composants par binding, ce qui permettrait de gérer tout le traiment par stream. Le composant serait immuable, on regénerait les listes de composants à chaque boucle. La suppression ne serait plus necéssaire que pour la "mort" d'une entité, ou sa mutation éventuelle : on pourrait gérer ça par un flag. Lors de la boucle de traitement, on ignore simplement les composants marqués par le flag.
    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.

  11. #11
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut
    Merci pour ta réponse, oui un vector d'as rien d'immuable je parlai de mes composants. Concernant les composants immuables ce qui m’ennuie le plus ce sont les grosses pertes de performance, après tout ce que tu m'as dit, je pense à beaucoup de choses qui pourraient me simplifier le travail, mais j'ai peur de faire mal les choses donc je préfère d'abord utilisé quelque chose de natif et qui fonctionne avant d'essayer d'améliorer ce type de conception à mon avantage. D'ailleurs le système de flag m'a l'air vachement intéressant à mettre en oeuvre, mais se sera pour un futur projet

    Sur ce, je vais appliquer ton code et encore, merci, c'est sympa d'avoir une discussion avec une personne qui explique les choses de manière pédagogue et simpliste

Discussions similaires

  1. vector de classe templatée
    Par Lintel-oo dans le forum Langage
    Réponses: 3
    Dernier message: 29/04/2012, 16h59
  2. Vector et classe
    Par sheep_one dans le forum Débuter
    Réponses: 4
    Dernier message: 26/01/2012, 07h47
  3. vector de classe
    Par Invité dans le forum SL & STL
    Réponses: 10
    Dernier message: 23/11/2008, 16h20
  4. Problème avec vector de classe template :(
    Par coyotte507 dans le forum Langage
    Réponses: 7
    Dernier message: 16/04/2008, 12h40
  5. [CONCEPTION] vector de classes heritées
    Par A-S-H dans le forum SL & STL
    Réponses: 9
    Dernier message: 28/12/2005, 09h50

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