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

Android Discussion :

Concaténer des chaînes de manière efficace


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut Concaténer des chaînes de manière efficace
    Bonjour à toutes et à tous,

    Dans une application, je souhaite enregistrer un fichier XML. Pour ce faire, je construit une chaîne composée des différentes informations puis j'enregistre cette chaîne. Le code est le suivant pour la formation de la chaîne :

    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
        for (int j = 0; j < ptsTrk.length; j++)
            strTrk = strTrk+trkGPX(ptsTrk[j].lat, ptsTrk[j].lon, ptsTrk[j].alti, ptsTrk[j].date);
     
        private static String trkGPX(double lat, double lon, double ele, String dt) {
            minmax(lat, lon);
            String str = "<trkpt lat=\""+String.format(Locale.US, "%.9f", lat)+"\" lon=\""+String.format(Locale.US, "%.9f", lon)+"\">"
                    +"<ele>"+String.format(Locale.US, "%.6f", ele)+"</ele>"
                    +"<time>"+dt+"</time>"
                    +"</trkpt>";
            return str;
        }
        private static void minmax(double lat, double lon) {
            if (lat < minLat) minLat = lat; else    if (lat > maxLat) maxLat = lat;
            if (lon < minLon) minLon = lon; else    if (lon > maxLon) maxLon = lon;
        }
    Sur mon Galaxy S2, pour 640 points (j de 0 à 639) cette procédure me prend 6 secondes ! Mais ce qui m'a étonné le plus est que ce qui consomme le plus de temps (4 secondes sur les 6) est le fait d'allonger la chaîne, c'est-à-dire de faire :

    Y a-t-il une méthode plus efficace ?

    Par ailleurs, l'instruction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String.format(Locale.US, "%.9f", lat)
    prend donc à elle seule prés de 2/(640 x 3) soit environ 1 milliseconde, ce qui me semble énorme. Y a-t-il une méthode de conversion plus rapide ?

    Merci de votre aide.

    Pierre

  2. #2
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Pour de la concaténation, utilise plutôt un StringBuilder (documentation), ou un StringBuffer si la synchronisation est important pour toi.

    As-tu réellement besoin d'un XML par contre ? Des POJO que tu pourrais sérialiser ne pourrait correspondre à ton besoin ? Ou du JSON, moins verbeux ? Ou encore une BDD SQLite ?
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  3. #3
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    Merci Hizin, je vais voir la doc du StringBuilder.

    Le XML n'est pas un choix personnel, c'est le format des fichiers d'échange de données cartographiques ".gpx".

    Cordialement.

    Pierre

  4. #4
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Ok.

    Dans ce cas, il faudrait peut-être t'orienter vers des bibliothèques de gestion XML. Je pense à XPath, qui est embarquée avec Android depuis la 2.2. Elle est réputée lente par contre, mais te permettra de construire les XML avec plus de flexibilité.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    757
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 757
    Par défaut
    Citation Envoyé par ChPr Voir le message
    Par ailleurs, l'instruction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String.format(Locale.US, "%.9f", lat)
    prend donc à elle seule prés de 2/(640 x 3) soit environ 1 milliseconde, ce qui me semble énorme. Y a-t-il une méthode de conversion plus rapide ?
    Oui c'est possible d'améliorer, même si je ne saurais te dire le temps que tu va gagner.
    La méthode format() est définie ainsi : public static String format (String format, Object... args)
    Cela veut dire que tu peux passer un nombre x d'arguments (x >= 0) qui remplaceront le paramètre args.
    Du coup, ta méthode peut se résumer à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    String str = "<trkpt lat=\"%.9f\" lon=\"%.9f\" ....";
    return String.format(Locale.US, str, lat, lon, ele);
    Tu évite ainsi plusieurs appels à la méthode format et tu évites de concaténer les chaines de caractères.

  6. #6
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    Merci simon de me rappeler cela. J'ai tout mis dans un seul String.format à chaque fois que possible, exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		String str = String.format(Locale.US, "<wpt lat=\"%.9f\" lon=\"%.9f\"><ele>%.6f</ele><name>%s</name><cmt></cmt><desc></desc><sym>%d</sym></wpt>", lat, lon, ele, nom, symb);
    Ca semble aller plus vite, mais ce n'est pas évident.

    Hizin : je n'ai pas utilisé de StringBuilder, mais un ArrayList car, autre détail embêtant, je dois compléter la deuxième ligne de mon fichier avec des valeurs que je ne connais qu'après avoir exploré toutes les valeurs du fichier (les min et max).

    Avec ces deux mesures combinées, le temps d’exécution a été divisé dans rapport proche de 10 !

    Cordialement.

    Pierre

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    757
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 757
    Par défaut
    Je pense tout de même qu'un StringBuilder serait beaucoup plus rapide.
    C'est quoi cette histoire de deuxième ligne ?

    Voilà ce que tu devrais faire :

    Tu te créé un pattern unique : genre {#1} et {#2} à l'endroit où il te faudra remplir ton min et ton max.
    Générer ton StringBuilder avec des .append(...) à chaque itération.
    A la fin des itérations, tu récupère la String correspondant, puis un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String str = stringBuilder.toString;
    str.replace("{#1}",min);
    str.replace("{#2}",max);
    Par ailleurs, le StringBuilder peut être énormément accéléré en lui donnant une taille d'initialisation. Celle ci est proportionnelle à ton nombre de points (ici ptsTrk.length). Ainsi tu peux initialiser ton StringBuilder comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    StringBuilder stringBuilder = new StringBuilder( 200 /*200 caractères par itération*/ * ptsTrk.length);

  8. #8
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    Dans la deuxième ligne, je dois donner les valeurs min et max que prennent les latitudes et longitudes des différents points que j'enregistre afin de délimiter la zone sans laquelle figureront tous les points.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    str.replace("{#1}",min);
    Dans le code ci-dessus, le nombre de caractères qui compose la valeur min n'est pas une constante, cela peut être par exemple 1.xxxxxxxxx ou -87.xxxxxxxxx (2 caractères de plus). Est-ce que cela ne posera pas de problème dans la structure StringBuilder ? NOTA : je pourrais prévoir de la place pour la chaîne la plus longue, mais alors, l'interpréteur de fichier .xml me signalera une erreur s'il rencontre des espaces bouche-trous.

    Cordialement.

    Pierre

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    757
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 757
    Par défaut
    Non, en fait, le StringBuilder permet de construire une chaine de caractère.
    Il est utile car l'Objet String est immutable (c'est à dire qu'il ne peut pas être modifié) et cela permet d'éviter des allocations trop nombreuses.
    Par ailleurs, l'objet StringBuilder ajuste automatiquement sa taille en fonction de ce que tu lui donne.
    Si tu créé un StringBuilder avec une contenance de 100 caractères par exemple, et que tu lui donne plus de 100 caractères, il va augmenter automatiquement sa taille (il y a peut être une formule derrière ça, mais je n'en sais trop rien).
    Ceci étant dis, le StringBuilder a déjà une contenance par défaut. Mais l'opération d'augmentation de taille est une opération coûteuse. Il faut l'ajuster au mieux dès le départ

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

Discussions similaires

  1. Concaténer des chaînes et des contenus de fichiers
    Par gvdmoort dans le forum Shell et commandes GNU
    Réponses: 3
    Dernier message: 01/08/2013, 17h08
  2. Concaténer des chaînes
    Par Mr_Chut dans le forum Télécharger
    Réponses: 0
    Dernier message: 01/12/2010, 10h31
  3. Réponses: 10
    Dernier message: 23/09/2008, 13h15
  4. Réponses: 20
    Dernier message: 05/01/2008, 11h52
  5. Comment concaténer des chaînes issues d'un fichier ini ?
    Par Neit_Sabes dans le forum Framework .NET
    Réponses: 10
    Dernier message: 27/09/2006, 09h28

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