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 :

Je n'arrive pas à utiliser Vector.indexOf()


Sujet :

Langage Java

  1. #1
    Candidat au Club
    Inscrit en
    Décembre 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Décembre 2010
    Messages : 12
    Points : 2
    Points
    2
    Par défaut Je n'arrive pas à utiliser Vector.indexOf()
    Bonjour,

    j'ai un soucis avec un Vector<char[]>. Je ne parviens à récupérer l'index d'aucun élément.

    J'ai donc un Vector déclaré comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static Vector<char[]> hashTab = null;
    Je l'initialise pas la suite avec des char[] de 2 caractères (AB,QW,ER, etc.) à partir d'un String[] :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    String[] str= {"BG", "WJ", "XB", "QW", "ZG"};
    for(int i=0; i<str.length ; i++)
    {
        hashTab.add(str[i].toCharArray());
    }
    Si je fais un j'obtiens bien QW. Mais si j'essaye de récupérer l'index de QW j'obtiens toujours -1.

    J'ai essayé comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char [] currentWord = new char[2];
    currentWord[0] = 'Q';
    currentWord[1] = 'W';
    int index = hashTab.indexOf(currentWord);
    ou encore comme ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int index = hashTab.indexOf("QW");
    mais apparement c'est pas ça... une idée ?

    merci d'avance !

    Popollux.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    bonjour.
    Je pense que la raison de ton problème est la suivante:
    indexOf utilise une comparaison par la méthode "equals" des valeurs. Or un tableau de caractères et une chaine de caractère de type String ne sont pas égaux à la comparaison par equals. Donc il ne retrouve pas l'élément recherché puisque tu transformes ta chaine en tableau de caractères. Est-ce vraiement nécessaire pour tes traitements? Tu pourrais très bien insérer les objets String tels quels (ils ont d'ailleurs dans leur interface des méthodes pour récupérer les caractères par index) et dans ce cas "QW" serait retrouvé par la méthode indexOf.

    PS: ne serais tu pas plus familier avec C ou C++ par hasard?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    String[] str= {"BG", "WJ", "XB", "QW", "ZG"};
    for(int i=0; i<str.length ; i++)
    {
        hashTab.add(str[i]);
    }
    int indexOfQw=hashTab.indexOf("QW");

  3. #3
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 567
    Points : 21 633
    Points
    21 633
    Par défaut
    Oui, c'est une limitation connue.

    Les méthodes comme contains(), indexOf(), remove(), ou tous les trucs qui cherchent un objet dans une collection, ont un point commun :
    elles se basent sur la méthode public boolean equals(Object).
    En gros, quand tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int index = vector.contains(monObjet);
    Ce qui va se passer, c'est une boucle sur tout les éléments de vector, et pour chaque élément e il va appeler :

    Si c'est true, la boucle considère que l'objet a été trouvé, si c'est false il passe au suivant.

    C'est clair ? Bien.

    C'est pour ça que quand on crée de nouvelles classes, dont les instances vont être stockées dans des collections et qu'on doit pouvoir les chercher à l'intérieur, il faut redéfinir la méthode public boolean equals(Object), qui dira donc si l'objet en cours est égal à l'objet passé en paramètre.
    Si on ne le fait pas, la classe héritera de la méthode equals() de Object, et a priori c'est pas ce qu'on veut.

    Bien. Et alors ?

    Et alors en Java, les tableaux n'implémentent pas equals(). Par conséquent, deux tableaux qui contiennent la même chose ne sont pas considérés égaux. Une instance de tableau n'est égale qu'à elle-même.

    Donc c'est pas possible avec des tableaux.

    => Ce que tu peux faire, c'est utiliser un Vector à la place de tableaux : ce qui te donne un Vector<Vector<Character>>

    => Et en fait, vu que les Vector ce n'est utile que si tu as besoin d'accès synchronisé, ce qui n'est pas le cas je suppose, tu ferais mieux d'utiliser des List : List<List<Character>>.

    => Par ailleurs, List<Character> ou char[], ce n'est utile que si les caractères doivent pouvoir être changés. Si ce n'est pas le cas, il faut bien sûr utiliser String. C'est juste plus simple.

  4. #4
    Candidat au Club
    Inscrit en
    Décembre 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Décembre 2010
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    @therwald : oui, je suis plutôt familier avec le C/C++.
    @thelvin : merci pour ces éclaircissements. Je suppose que dans mon cas la méthode equals() doit comparer les adresses mémoire de chaque instance, donc comme tu dis c'est forcément faux tout le temps, sauf pour soi-même.

    Je pense que je vais simplement passer de Vector à List et redéfinir la méthode equals() pour les char[].

    J'utilise des char[] pour des raisons de sécurité, puisqu'apparemment les String sont conservés en mémoire, même après déréférencement, pour des raisons d'optimisation.

    Merci !

  5. #5
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    À noter que tu peux aussi le faire "à la mano" avec la méthode Arrays.equals().

  6. #6
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Je ne suis pas certain de comprendre tes considérations de sécurité?
    Quoi qu'il en soi, tu ne peux pas redéfinir equals pour char[], car cette classe est une classe spéciale créée par l'environnement java.
    A moins que tu n'utilise une méthode de recherche externe pour chercher dans ta collection, mais ce serait un peu réinventer la roue...
    Il existe des classes de chaines de caractères mutable (StringBuilder, StringBuffer) qui ne partagent pas leurs buffers, puisqu'ils sont susceptibles de modifications, donc je suppose qu'ils sont supprimés lors de la garbage collection.

  7. #7
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Il peut toujours coder une classe de Wrap. Ou, comme je le disais, coder à la main le indexOf, en évitant la double boucle avec l'utilisation de Arrays.equals().

  8. #8
    Expert éminent sénior
    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 : 45
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    cassez vous pas le cul, transformez votre char[] en un String, et tout rentrera dans l'ordre. String implémente equals, donc aucun soucis.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    static Vector<String> hashTab = null;
    String[] str= {"BG", "WJ", "XB", "QW", "ZG"};
    for(int i=0; i<str.length ; i++)
    {
        hashTab.add(str[i]);
    }
     
    String currentWord = "QW";
    int index = hashTab.indexOf(currentWord);
    Pour info, on ne manipule presque jamais des char[] en java, la String étant bien plus pratique puisque un char[] est souvent dans la logique du programmeur une "chaine de caractères". Le char[], c'est surement un réflexe venant du C que vous avez

  9. #9
    Candidat au Club
    Inscrit en
    Décembre 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Décembre 2010
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    @tchize, comme je disais plus haut :
    J'utilise des char[] pour des raisons de sécurité, puisqu'apparemment les String sont conservés en mémoire, même après déréférencement, pour des raisons d'optimisation.
    Y a ce genre d'info là par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    http://blog.soat.fr/2010/08/java-securite-et-les-char/
    Maintenant si c'est du flan je vais prendre des String, mais pour l'instant à la vue de ce que j'ai pu lire, je reste sur mes char[], et ça n'est pas un réflexe de C.

    Comme dit Rei Ichido San, je vais voir ce que ça donne l'histoire de "coder à la main le indexOf".

  10. #10
    Candidat au Club
    Inscrit en
    Décembre 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Décembre 2010
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Bon... google n'est plus mon ami, je n'ai pas trouvé grand chose pour "coder à la main le indexOf", et après ce que vous m'avez dis je ne vois plus ce trop ce que je peux faire avec mes char[].

    A la base j'utilise la méthode getPassword() d'un JPasswordField qui renvoie un char[] (à la place d'un String, pour les raisons citées avant).
    Donc l'idée déjà, ça n'est pas du tout de transformer ça en String, sinon les gars qui on pondu l'API auraient renvoyé un String.

    Pourquoi on pédale tellement dans la semoule pour manipuler ce type de données ? Çà me paraît quand même pas complètement exotique de vouloir faire une liste de char[].
    A côté de ça la classe Character à l'air franchement orienté texte, c'est pas ce que je veux non plus.

    Peut-être à Noël...

  11. #11
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Je suis pas totalement convaincu par l'argument de sécurité, mais anyway, la méthode peut ressembler à ça (non testé) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	public int indexOf(Vector<char[]> list, char[] toSearch ) {
    		// A voir si tu preferes -1 ou lancer une exception
    		if (list == null || list.size() == 0) return -1;
    		for (int i = 0 ; i < list.size() ; i ++ ) {
    			if (Arrays.equals(list.get(i), toSearch)) return i;
    		}
    		return -1;
    	}

  12. #12
    Candidat au Club
    Inscrit en
    Décembre 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Décembre 2010
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Merci beaucoup Rei Ichido,

    pour l'argument de sécurité je vais encore chercher de la littérature sur le sujet. Après, rien que pour le principe, j'aimerais bien aboutir avec des char[].

    Par contre j'ai un soucis pour coder le indexOf, car je ne vois pas où je dois le mettre.

    J'ai finalement changé mes Vector en List. Le indexOf est donc celui de List. Ma classe ne surchargent pas List, je ne vois pas où je dois écrire ce code pour qu'il soit pris en compte par List.
    La par exemple je l'ai mis au même niveau que mon main et List.indexOf() appelle toujours le code natif. Pfff je galère trop.

  13. #13
    Expert éminent sénior
    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 : 45
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Citation Envoyé par popollux Voir le message
    @tchize, comme je disais plus haut :

    Y a ce genre d'info là par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    http://blog.soat.fr/2010/08/java-securite-et-les-char/
    Maintenant si c'est du flan je vais prendre des String, mais pour l'instant à la vue de ce que j'ai pu lire, je reste sur mes char[], et ça n'est pas un réflexe de C.
    C'est du pipo

    Seule les String hardcodées dans ton code son gardée en mémoire. Donc tu n'y perd rien puisque, de toutes facons, ces string sont déjà dans ta classe. ainsi, quand tu fais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    String[] str= {"BG", "WJ", "XB", "QW", "ZG"};
    Les 5 string en question sont "interned" pour économiser la mémoire (pas pour en faire perdre).
    Plus tard quand tu aura dans ton code

    ce sera la même instance qui sera utilisée. tu ne perd pas de mémoire avec ça. Et quand à la sécurité:
    si tu lit la string depuis un Stream ou un clavier, celle-ci n'est jamais "internée", sinon au bout de 2 heure ton programme serait engorgé d'un point de vue mémoire
    si tu lit la string depuis ta classe (String s = "1234") , elle est internée, masi avec ou sans, tu a le problème de sécurité puisque cette valeur est dans le bytecode de la classe :/

  14. #14
    Candidat au Club
    Inscrit en
    Décembre 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Décembre 2010
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    Merci Tchize_,

    je connaissais le coup des String qu'on déclare en dur. Pour les String affectées dynamiquement, je le note =)

    Après, comme disait Ben-Hur, je vais essayer d'aboutir avec mes char[], pour la science

    VERS L'INFINI ET AU-DELAAAAAAAA !!!

  15. #15
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Citation Envoyé par popollux Voir le message
    La par exemple je l'ai mis au même niveau que mon main et List.indexOf() appelle toujours le code natif. Pfff je galère trop.
    Evidemment il faut remplacer l'appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int index = indexOf(hashTab, currentWord);
    La méthode est ou bien à caser dans une classe utilitaire, ou bien à mettre dans la classe appelante (si tu n'y fais appel qu'à un endroit). Si c'est appelé dans ton main, contexte statique => mettre la méthode en static.

  16. #16
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 567
    Points : 21 633
    Points
    21 633
    Par défaut
    Oui enfin, c'est assez vrai que beaucoup de choses, dans du code classique, peut décider de garder des références vers une String pour un oui ou pour un non, alors que ça n'arrive pas souvent pour les char[].
    On ne peut pas facilement compter sur le fait que personne ne le fait.

    Il y a notamment le String.substring(), qui peut décider de garder référence vers sa String d'origine au lieu de dupliquer l'intervalle qui la concerne.
    Bref, la bibliothèque de base Java elle-même fait preuve de prudence de ce côté-là, par exemple pour lire des mots de passe. Je ne suis donc pas sûr que ce soit entièrement du pipeau.

  17. #17
    Candidat au Club
    Inscrit en
    Décembre 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Décembre 2010
    Messages : 12
    Points : 2
    Points
    2
    Par défaut
    @Rei Ichido : et en plus ça marche... arigato gosaimasu ^_^

    @thelvin : ça tombe bien parce que comme ça marche, je vais pas tout réécrire en String =)

    Merci à tous !

  18. #18
    Expert éminent sénior
    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 : 45
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Oui enfin, c'est assez vrai que beaucoup de choses, dans du code classique, peut décider de garder des références vers une String pour un oui ou pour un non, alors que ça n'arrive pas souvent pour les char[].
    .
    Y a pas de raison, c'est pas différents. Les strings gardées en mémoire ne sont que celles qui l'auraient été de toutes façons!
    Et de toutes facons protéger le programme contre une lecture agressive de sa zone mémoire n'a aucun sens. Si la personnes à accès à la machine, elle a aussi facile de patcher votre programme ou lui substituer un leurre pour pomper les mtos de passe :/ C'est de la paranoia inutile et les char[], tout comme les String resteront de toutes facon en mémoire tant qu'on aura pas passé dessus le GC, ce qui peut ne jamais arriver.

  19. #19
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 567
    Points : 21 633
    Points
    21 633
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Y a pas de raison, c'est pas différents. Les strings gardées en mémoire ne sont que celles qui l'auraient été de toutes façons!
    D'abord il y a une différence "sociale." Les codeurs ne traitent pas les String de la même manière qu'ils traitent les char[]. Peut-être qu'ils devraient en toute logique, mais ce n'est pas ce qui se passe dans la réalité.
    Ensuite, un char[] n'est pas immutable. Donc si, c'est différent.

    Citation Envoyé par tchize_ Voir le message
    Et de toutes facons protéger le programme contre une lecture agressive de sa zone mémoire n'a aucun sens. Si la personnes à accès à la machine, elle a aussi facile de patcher votre programme ou lui substituer un leurre pour pomper les mtos de passe :/ C'est de la paranoia inutile et les char[], tout comme les String resteront de toutes facon en mémoire tant qu'on aura pas passé dessus le GC, ce qui peut ne jamais arriver.
    Certes. C'est aussi ce que je pense en tout cas. Toutefois, la bibliothèque de base Java elle-même a tendance à utiliser char[] plutôt que String dans ce genre de cas. Et dans de nombreux domaines, elle a fait ses preuves. Du moins son contenu post-1.4 l'a fait.

    Du coup, je me demande si c'est juste s'ils ont cédé aux injonctions newbies, ou s'il y a vraiment des choses auxquelles je ne pense pas.

  20. #20
    Expert éminent sénior
    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 : 45
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    comme vous le dites, le char[] est pas mutable. La considération de sécurité ici, c'est de dire: dès que vous l'avez traité, vous le réinitialisez en mettant des 0 à la place, ca évite d'attendre que le GC passe dessus et qu'on réinitialise la zone mémoire pour ça.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char[] password = passwordField.getPassword();
    passwordField.selectAll();
    resetFocus();
    boolean success = validatePassword(password);
    Arrays.fill(password, '0');
    if (success) .....
    Ca ne fait que limiter dans le temps un risque qui existe de toutes façon: la lecture par l'extérieur de cette zone mémoire. Et pour moi si cette lecture est possible, vous êtes déjà dans le caca de toutes façons. Reste le risque de la swappe, a évaluer éventuellement, c'est le risque que la zone mémoire du mot de passe soit swappée sur le disque, ce qui rendrait ce mot de passe accessible à quiconque volerais dans les minutes qui suivent le disque dur.... (Tant que la zone n'est pas réécrite par autre chose en somme)

    Bref la sécurité n'est pas dans le fait d'utiliser char[] mais dans ce que vous faites avec le char une fois que vous l'avez traité. Si vous ne le remettez pas à 0, vous ne gagnez rien sur le strings.

Discussions similaires

  1. J'arrive pas à utiliser JProgressBar !
    Par med_anis_dk dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 04/06/2007, 08h22
  2. Réponses: 2
    Dernier message: 12/04/2007, 09h42
  3. Je n'arrive pas à utiliser le Double buffering
    Par Yann39 dans le forum AWT/Swing
    Réponses: 43
    Dernier message: 21/01/2007, 23h14
  4. J'arrive pas à utiliser l'authentification par clé sur ma debian
    Par biglittlekiss dans le forum Sécurité
    Réponses: 2
    Dernier message: 11/12/2006, 14h15
  5. Réponses: 4
    Dernier message: 22/05/2006, 12h46

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