2011-05-09 15 views

Respuesta

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

Advertencia:en contra del propósito de StringBuilder, pero sí lo que has pedido.


mejor técnica de (aunque todavía no es ideal):

  1. inversa cada cadena que desea insertar.
  2. Adjuntar cada cadena a un StringBuilder.
  3. invierta el enteroStringBuilder cuando haya terminado.

Esto a su vez un O (n ²) solución en O (n).

+0

... ya que hace que 'AbstractStringBuilder' mueva todos los contenidos más allá del índice de inserción para encontrar espacio para los insertados. Sin embargo, eso es un detalle de implementación, no uno de principio. – entonio

+1

@entonio: De hecho, pero es un detalle * muy crítico *. :) – Mehrdad

+1

Veo, parece que no debería estar usando StringBuilder entonces, muchas gracias – user685275

18

puede utilizar strbuilder.insert(0,i);

7

Tal vez me falta algo, pero que desea terminar con una cadena que tiene este aspecto, "999897969594...", correcto?

StringBuilder sb = new StringBuilder(); 
for(int i=99;i>=0;i--){ 
    sb.append(String.valueOf(i)); 
} 
+0

Extraño este post no obtuvo mucha votación al proporcionar la solución mediante la manipulación inteligente del ciclo, –

+1

@ nom-mon-ir acaba de invertir el String. No responde cómo agregar a la izquierda. –

+0

Logra el efecto deseado. – Speck

3

Este hilo es bastante antiguo, pero también se podría pensar en una solución recursiva pasar el StringBuilder para llenar. Esto permite evitar cualquier proceso inverso, etc. Solo necesita diseñar su iteración con una recursión y cuidadosamente decidir por una condición de salida.

public class Test { 

    public static void main(String[] args) { 
     StringBuilder sb = new StringBuilder(); 
     doRecursive(sb, 100, 0); 
     System.out.println(sb.toString()); 
    } 

    public static void doRecursive(StringBuilder sb, int limit, int index) { 
     if (index < limit) { 
      doRecursive(sb, limit, index + 1); 
      sb.append(Integer.toString(index)); 
     } 
    } 
} 
6

Como solución alternativa se puede utilizar una estructura LIFO (como una pila) para almacenar todas las cuerdas y cuando haya terminado simplemente tomar todos estos elementos para ponerlos en el StringBuilder. Naturalmente, invierte el orden de los elementos (cadenas) que se colocan en él.

Stack<String> textStack = new Stack<String>(); 
// push the strings to the stack 
while(!isReadingTextDone()) { 
    String text = readText(); 
    textStack.push(text); 
} 
// pop the strings and add to the text builder 
String builder = new StringBuilder(); 
while (!textStack.empty()) { 
     builder.append(textStack.pop()); 
} 
// get the final string 
String finalText = builder.toString(); 
+3

Se debe usar 'ArrayDeque' en lugar de' Stack'. "La interfaz {@link Deque} y sus implementaciones proporcionan un conjunto más completo y consistente de las operaciones de la pila LIFO, que se deben utilizar con preferencia a esta clase". –

0

Tenía un requisito similar cuando tropecé con esta publicación. Quería una manera rápida de construir una cadena que pueda crecer desde ambos lados, es decir. agregue nuevas letras en el frente, así como en la parte posterior arbitrariamente. Sé que esta es una publicación anterior, pero me inspiró para probar algunas formas de crear cadenas y pensé en compartir mis hallazgos. También estoy usando algunos Java 8 construcciones en este, que podrían haber optimizado la velocidad en los casos 4 y 5.

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

El Gist anterior tiene el código detallado que cualquier persona puede ejecutar. Tomé algunas formas de hacer crecer cadenas en esto; 1) Agregar a StringBuilder, 2) Insertar al frente de StringBuilder como se muestra en @Mehrdad, 3) Insertar parcialmente desde el frente y al final del StringBuilder, 4) Usar una lista para agregar desde el final, 5) Usar un Deque para anexar desde el frente.

// 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("")); 

Voy a centrarme en la parte delantera anexar solo casos, es decir. caso 2 y caso 5. La implementación de StringBuilder decide internamente cómo crece el búfer interno, que además de mover todo el búfer de izquierda a derecha en caso de agregarse al frente limita la velocidad. Mientras que el tiempo empleado al insertar directamente en la parte frontal del StringBuilder crece a valores realmente altos, como se muestra en @Mehrdad, si la necesidad es solo tener cadenas de longitud de menos de 90k caracteres (que aún es mucho), la inserción frontal construya una Cadena al mismo tiempo que le llevaría construir una Cadena de la misma longitud añadiéndola al final. Lo que estoy diciendo es que la penalización de tiempo de tiempo patea y es enorme, pero solo cuando tienes que construir cadenas realmente grandes. Uno podría usar un deque y unir las cuerdas al final como se muestra en mi ejemplo. Pero StringBuilder es un poco más intuitivo de leer y codificar, y la penalización no importaría para cadenas más pequeñas.

En realidad, el rendimiento para el caso 2 es mucho más rápido que el caso 1, que no parece entender. Supongo que el crecimiento para el búfer interno en StringBuilder sería el mismo en caso de anexión frontal y anexión posterior. Incluso configuré el montón mínimo en una cantidad muy grande para evitar demoras en el crecimiento del montón, si eso hubiera jugado un papel. Tal vez alguien que tenga un mejor entendimiento pueda comentar a continuación.