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

Java Discussion :

fonctionnement de StringBuffer


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 114
    Par défaut fonctionnement de StringBuffer
    Bonjour,

    il y a quelque-chose que je ne comprends pas dans la classe StringBuffer : si je vide un StringBuffer (en utilisant invariablement setLength(0) ou delete(0, sb.length())) à l'intérieur d'un bloc (entre deux accolades), il arrive qu'en sortant des accolades il y ait à nouveau quelque-chose dans le StringBuffer. C'est à dire par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    if (current != last){
    	indices[current - 1] = i - sb.length();
    	last = current;
    	sb.setLength(0);
    	System.out.println(sb);
    	System.out.println(sb.length());
    }
    System.out.println(sb);
    System.out.println(sb.length());
    Pour le premier affichage tout va bien et pour le second, sb vaut l'ancienne valeur avec l'ancienne taille. Je précise que parfois cela fonctionne bien (la taille reste à 0, etc.).

    J'ai également essayé de faire ma propre classe MyStringBuffer en version simpliste :

    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
    public class MyStringBuffer {
    	int size;
    	int pos = 0;
    	char[] buffer;
     
    	MyStringBuffer(int size){
    		this.size = size;
    		buffer = new char[size];
    	}
     
    	void append(char c){
    		buffer[pos] = c;
    		pos++;
    	}
     
    	int length(){
    		return pos;
    	}
     
    	void clear(){
    		pos = 0;		
    	}
     
    	public String toString(){
    		return new String(buffer, 0, pos);
    	}
    }
    et le même phénomène se produit. Comment se fait-ce ?

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    StringBuffer fonctionne parfaitement, donc il doit surement y avoir un problème dans ton algorithme...

    De plus je ne vois pas trop l'intérêt de recoder son propre "StringBuffer"...


    a++

  3. #3
    Membre Expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Par défaut
    Moi je ne m'embêterai pas, au lieu de faire : sb.setLength(0); je ferais sb = new StringBuffer();.

  4. #4
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par natha Voir le message
    Moi je ne m'embêterai pas, au lieu de faire : sb.setLength(0); je ferais sb = new StringBuffer();.
    sb.setLength(0) fonctionne parfaitement et cela permet de réutiliser le même tableau du StringBuffer sans refaire d'allocation. Si tu traites de grosses quantité de données le gain peut être sensible


    a++

  5. #5
    Membre Expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    sb.setLength(0) fonctionne parfaitement et cela permet de réutiliser le même tableau du StringBuffer sans refaire d'allocation. Si tu traites de grosses quantité de données le gain peut être sensible
    Jamais eu l'occasion d'utiliser #setLength par contre mon commentaire permet de se rendre compte rapidement si le problème vient effectivement de setLength ou d'ailleurs.

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par natha Voir le message
    Jamais eu l'occasion d'utiliser #setLength par contre mon commentaire permet de se rendre compte rapidement si le problème vient effectivement de setLength ou d'ailleurs.
    Oui en effet je n'avais pas pensé à cela

    a++

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 114
    Par défaut
    as-tu vérifié que ton code ne soit pas exécuté plusieurs fois (par exemple un listener peut être exécuté plusieurs fois lors d'un changement d'état)
    Je ne pense pas que ce soit le cas car il n'y a pas de processus léger, pas d'interface graphique, etc. rien que mon processus ; et l'affichage est bien effectué séquentiellement.

    mon commentaire permet de se rendre compte rapidement si le problème vient effectivement de setLength ou d'ailleurs.
    En utilisant un new StringBuffer() le problème survient encore. Je sens que quand je vais trouver d'où vient mon problème je vais me taper la grosse honte

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 114
    Par défaut
    StringBuffer fonctionne parfaitement, donc il doit surement y avoir un problème dans ton algorithme...
    Je sais qu'il ne faut pas rejeter la faute sur les autres et surtout pas sur les classes de chez java, mais là j'ai du mal à continuer de me le dire : il ne se passe absolument rien d'autre entre les deux affichages que la fermeture de l'accolade.

    je ne vois pas trop l'intérêt de recoder son propre "StringBuffer"...
    Si StringBuffer fonctionne parfaitement il n'y a évidemment aucun intéret.

  9. #9
    Membre chevronné Avatar de Bezout
    Profil pro
    Développement
    Inscrit en
    Septembre 2003
    Messages
    234
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développement

    Informations forums :
    Inscription : Septembre 2003
    Messages : 234
    Par défaut
    recrée un StringBuffer avec une taille initiale de 16.

    Je trouve ca pas terrible comme technique pour vider un buffer surtout si sb a été initialisé comme ca
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    StringBuffer sb = new StringBuffer(256);
    pour par exemple eviter les réallocations mémoire.

    Je pense qu'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sb.delete(0, sb.length());
    est préférable.

    Dommage qu'il n'y ait pas une méthode clear comme pour une collection.

  10. #10
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par yarf Voir le message
    Je sais qu'il ne faut pas rejeter la faute sur les autres et surtout pas sur les classes de chez java, mais là j'ai du mal à continuer de me le dire : il ne se passe absolument rien d'autre entre les deux affichages que la fermeture de l'accolade.
    Pourtant tu le dis toi même : tu obtiens le même résultat avec ta propre classe StringBuffer...

    a++

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 114
    Par défaut
    Pourtant tu le dis toi même : tu obtiens le même résultat avec ta propre classe StringBuffer...
    Oui et c'est pour cela que je suis complètement perdu : d'un côté une preuve que la classe est bonne et de l'autre une mise en évidence simple d'un problème apparaissant quand j'utilise cette même classe. C'est pour cela que je m'adresse à vous.

    sb.setLength(0) recrée un StringBuffer avec une taille initiale de 16.

    Je trouve ca pas terrible comme technique pour vider un buffer surtout si sb a été initialisé comme ca

    StringBuffer sb = new StringBuffer(256);

    pour par exemple eviter les réallocations mémoire.

    Je pense qu'un sb.delete(0, sb.length()) est préférable.
    le code de setLength dans AbstractStringBuilder (StringBuffer en hérite) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        public void setLength(int newLength) {
    	if (newLength < 0)
    	    throw new StringIndexOutOfBoundsException(newLength);
    	if (newLength > value.length)
    	    expandCapacity(newLength);
     
    	if (count < newLength) {
    	    for (; count < newLength; count++)
    		value[count] = '\0';
    	} else {
                count = newLength;
            }
        }
    et celui de delete :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        public AbstractStringBuilder delete(int start, int end) {
    	if (start < 0)
    	    throw new StringIndexOutOfBoundsException(start);
    	if (end > count)
    	    end = count;
    	if (start > end)
    	    throw new StringIndexOutOfBoundsException();
            int len = end - start;
            if (len > 0) {
                System.arraycopy(value, start+len, value, start, count-end);
                count -= len;
            }
            return this;
        }
    Donc si on n'a pas à se préoccuper de la capacité du tableau (ce qui est le cas pour moi), setLength(0) est préférable non ? Enfin c'est un autre problème...

  12. #12
    Membre chevronné Avatar de Bezout
    Profil pro
    Développement
    Inscrit en
    Septembre 2003
    Messages
    234
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développement

    Informations forums :
    Inscription : Septembre 2003
    Messages : 234
    Par défaut
    En JDK 1.4.2 c'était différent

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
                    } else {
                        // If newLength is zero, assume the StringBuffer is being
                        // stripped for reuse; Make new buffer of default size
                        value = new char[16];
                        shared = false;
                    }

  13. #13
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par yarf Voir le message
    Donc si on n'a pas à se préoccuper de la capacité du tableau (ce qui est le cas pour moi), setLength(0) est préférable non ?
    Oui, le setLength(0) ne fait que de modifier un attribut. La mémoire utilisé et alloué pour le buffer n'est pas touché et peut être réutilisé.


    Pour en revenir à ton problème : as-tu vérifié que ton code ne soit pas exécuté plusieurs fois (par exemple un listener peut être exécuté plusieurs fois lors d'un changement d'état)


    a++

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

Discussions similaires

  1. String et StringBuffer vitesse et fonctionnement
    Par damien77 dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 12/05/2008, 13h42
  2. Réponses: 5
    Dernier message: 14/05/2003, 14h51
  3. [Turbo Pascal] TP7 fonctionne en QWERTY
    Par callahan dans le forum Turbo Pascal
    Réponses: 9
    Dernier message: 08/02/2003, 21h49
  4. Prb de fonctionnement dans SaveDialog avecInitialDir
    Par boyerf dans le forum Composants VCL
    Réponses: 4
    Dernier message: 12/12/2002, 21h46
  5. ca ne fonctionne pas (generateur auto-incrémentant)
    Par tripper.dim dans le forum SQL
    Réponses: 7
    Dernier message: 26/11/2002, 00h10

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