97 votes

java : utiliser StringBuilder pour insérer au début

Je ne pouvais le faire qu'avec String, par exemple :

String str="";
for(int i=0;i<100;i++){
    str=i+str;
}

Existe-t-il un moyen d'y parvenir avec StringBuilder ? Merci.

3voto

Siddharth Wagle Points 239

J'avais un besoin similaire lorsque je suis tombé sur ce post. Je voulais un moyen rapide de construire une chaîne qui puisse s'étendre des deux côtés, c'est-à-dire ajouter de nouvelles lettres à l'avant comme à l'arrière, de façon arbitraire. Je sais qu'il s'agit d'un ancien article, mais il m'a incité à essayer plusieurs façons de créer des chaînes de caractères et j'ai pensé que je devais partager mes découvertes. J'utilise également certaines constructions Java 8, ce qui aurait pu optimiser la vitesse dans les cas 4 et 5.

https://gist.github.com/SidWagz/e41e836dec65ff24f78afdf8669e6420

Le Gist ci-dessus contient le code détaillé que tout le monde peut exécuter. J'ai pris plusieurs façons de faire croître les chaînes de caractères dans ce code ; 1) Append to StringBuilder, 2) Insert to front of StringBuilder as shown by @Mehrdad, 3) Partially insert from front as well as end of the StringBuilder, 4) Using a list to append from end, 5) Using a Deque to append from the front.

// Case 2    
StringBuilder build3 = new StringBuilder();
IntStream.range(0, MAX_STR)
                    .sequential()
                    .forEach(i -> {
                        if (i%2 == 0) build3.append(Integer.toString(i)); else build3.insert(0, Integer.toString(i));
                    });
String build3Out = build3.toString();

//Case 5
Deque<String> deque = new ArrayDeque<>();
IntStream.range(0, MAX_STR)
                .sequential()
                .forEach(i -> {
                    if (i%2 == 0) deque.addLast(Integer.toString(i)); else deque.addFirst(Integer.toString(i));
                });

String dequeOut = deque.stream().collect(Collectors.joining(""));

Je me concentrerai uniquement sur les cas de l'appendice avant, c'est-à-dire les cas 2 et 5. L'implémentation de StringBuilder décide en interne de la croissance du tampon interne, ce qui, en dehors du déplacement de tout le tampon de gauche à droite en cas d'ajout frontal, limite la vitesse. Alors que le temps pris lors de l'insertion directe à l'avant du StringBuilder augmente jusqu'à des valeurs vraiment élevées, comme montré par @Mehrdad, si le besoin est d'avoir seulement des chaînes de longueur inférieure à 90k caractères (ce qui est encore beaucoup), l'insertion avant construira une chaîne dans le même temps qu'il faudrait pour construire une chaîne de la même longueur en ajoutant à la fin. Ce que je veux dire, c'est que la pénalité de temps est effectivement importante, mais seulement lorsque vous devez construire des chaînes de caractères vraiment énormes. On pourrait utiliser un deque et joindre les chaînes à la fin comme indiqué dans mon exemple. Mais StringBuilder est un peu plus intuitif à lire et à coder, et la pénalité n'aurait pas d'importance pour des chaînes plus petites.

En fait, les performances du cas 2 sont beaucoup plus rapides que celles du cas 1, ce que je ne semble pas comprendre. Je suppose que la croissance du tampon interne dans StringBuilder serait la même dans le cas d'un front append et d'un back append. J'ai même fixé le tas minimum à un montant très élevé pour éviter un retard dans la croissance du tas, si cela a pu jouer un rôle. Peut-être que quelqu'un qui a une meilleure compréhension peut commenter ci-dessous.

1voto

Difference Between String, StringBuilder And StringBuffer Classes
String
String is immutable ( once created can not be changed )object. The object created as a
String is stored in the Constant String Pool.
Every immutable object in Java is thread-safe, which implies String is also thread-safe. String
can not be used by two threads simultaneously.
String once assigned can not be changed.
StringBuffer
StringBuffer is mutable means one can change the value of the object. The object created
through StringBuffer is stored in the heap. StringBuffer has the same methods as the
StringBuilder , but each method in StringBuffer is synchronized that is StringBuffer is thread
safe .
Due to this, it does not allow two threads to simultaneously access the same method. Each
method can be accessed by one thread at a time.
But being thread-safe has disadvantages too as the performance of the StringBuffer hits due
to thread-safe property. Thus StringBuilder is faster than the StringBuffer when calling the
same methods of each class.
String Buffer can be converted to the string by using
toString() method.

    StringBuffer demo1 = new StringBuffer("Hello") ;

// The above object stored in heap and its value can be changed.
/
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
StringBuilder is the same as the StringBuffer, that is it stores the object in heap and it can also
be modified. The main difference between the StringBuffer and StringBuilder is
that StringBuilder is also not thread-safe.
StringBuilder is fast as it is not thread-safe.
/
// The above object is stored in the heap and its value can be modified
/
// Above statement is right as it modifies the value which is allowed in the StringBuilder

1voto

sachyy Points 165

Vous pouvez utiliser la méthode d'insertion avec le décalage. Si le décalage est défini sur '0', cela signifie que vous ajoutez le début de votre StringBuilder.

StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
    sb.insert(0,i);
}

NOTE : comme la méthode d'insertion accepte tous les types de primitives, vous pouvez utiliser pour int, long, char[] etc.

0voto

Trying Points 4092

Pourquoi pas :

StringBuilder builder = new StringBuilder();
for(int i=99;i>=0;i--){
    builder.append(Integer.toString(i));
}
builder.toString();

OU

StringBuilder builder = new StringBuilder();
for(int i=0;i<100;i++){
  builder.insert(0, Integer.toString(i));
}
builder.toString();

Mais avec cela, vous faites l'opération O(N^2) au lieu de O(N).

Extrait de la documentation de Java :

Insère la représentation de la chaîne de l'argument Objet dans cette séquence de caractères. séquence de caractères. L'effet global est exactement le même que si le deuxième argument était converti en chaîne de caractères par la méthode String.valueOf(Object) et les caractères de cette chaîne sont ensuite insérés dans cette séquence de caractères au décalage indiqué.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X