Una forma sencilla de repetir una cadena en java



14 Answers

Aquí está la versión más corta (se requiere Java 1.5+):

repeated = new String(new char[n]).replace("\0", s);

Donde n es el número de veces que desea repetir la cadena y s es la cadena para repetir.

No hay importaciones o bibliotecas necesarias.

java string

Estoy buscando un simple método u operador común que me permita repetir algunos String n veces. Sé que podría escribir esto usando un bucle for, pero deseo evitar los bucles siempre que sea necesario y debería existir un método directo simple en algún lugar.

String str = "abc";
String repeated = str.repeat(3);

repeated.equals("abcabcabc");

Relacionado con:

repetir cadena javascript Crear NSString repitiendo otra cadena un número dado de veces

Editado

Intento evitar los bucles cuando no son completamente necesarios porque:

  1. Se agregan al número de líneas de código incluso si están ocultas en otra función.

  2. Alguien que lea mi código tiene que averiguar qué estoy haciendo en ese bucle for. Incluso si está comentado y tiene nombres de variables significativas, todavía tienen que asegurarse de que no está haciendo nada "inteligente".

  3. A los programadores les encanta poner cosas inteligentes en los bucles, incluso si escribo "para hacer solo lo que se pretende que haga", eso no impide que alguien venga y agregue alguna "solución" inteligente adicional.

  4. Muy a menudo son fáciles de equivocarse. Para los bucles que involucran índices tienden a generarse por un error.

  5. Para los bucles, a menudo se reutilizan las mismas variables, lo que aumenta la posibilidad de encontrar errores de alcance realmente difíciles.

  6. Para los bucles, aumentar el número de lugares que un cazador de errores tiene que buscar.




Si está utilizando Java <= 7 , esto es tan simple como se obtiene:

// create a string made up of n copies of string s
String.format("%0" + n + "d", 0).replace("0",s);

En Java 8 y superior hay una manera fácil:

// create a string made up of n copies of string s
String.join("", Collections.nCopies(n, s));

Java 11 agregó un nuevo método de repeat​(int count) específicamente para este ( download.java.net/java/early_access/jdk11/docs/api/java.base/… )

int n = 3;
"abc".repeat(n);



Aquí hay una forma de hacerlo utilizando solo funciones de cadena estándar y sin bucles explícitos:

// create a string made up of  n  copies of  s
repeated = String.format(String.format("%%%ds", n), " ").replace(" ",s);



Con java-8 , también puedes usar Stream.generate .

import static java.util.stream.Collectors.joining;
...
String repeated = Stream.generate(() -> "abc").limit(3).collect(joining()); //"abcabcabc"

y puede envolverlo en un método de utilidad simple si es necesario:

public static String repeat(String str, int times) {
   return Stream.generate(() -> str).limit(times).collect(joining());
}



Esto contiene menos caracteres que tu pregunta

public static String repeat(String s, int n) {
    if(s == null) {
        return null;
    }
    final StringBuilder sb = new StringBuilder(s.length() * n);
    for(int i = 0; i < n; i++) {
        sb.append(s);
    }
    return sb.toString();
}



Usando Dollar es tan simple como escribir:

@Test
public void repeatString() {
    String string = "abc";
    assertThat($(string).repeat(3).toString(), is("abcabcabc"));
}

PD: la repetición funciona también para array, List, Set, etc.




Solución OOP

Casi todas las respuestas proponen una función estática como solución, pero pensando en Objetos (por motivos de reutilización y claridad), se me ocurrió una Solución a través de la Delegación a través de la Interfaz de Secuencia de Chars (que también abre la facilidad de uso en Clases de CharSecuencia mutables).

La siguiente clase se puede usar con o sin Separator-String / CharSequence y cada llamada a "toString ()" crea la String final repetida. La entrada / separador no solo se limita a String-Class, sino que puede ser cualquier clase que implemente CharSequence (por ejemplo, StringBuilder, StringBuffer, etc.).

Código fuente:

/**
 * Helper-Class for Repeating Strings and other CharSequence-Implementations
 * @author Maciej Schuttkowski
 */
public class RepeatingCharSequence implements CharSequence {
    final int count;
    CharSequence internalCharSeq = "";
    CharSequence separator = "";
    /**
     * CONSTRUCTOR - RepeatingCharSequence
     * @param input CharSequence to repeat
     * @param count Repeat-Count
     */
    public RepeatingCharSequence(CharSequence input, int count) {
        if(count < 0)
            throw new IllegalArgumentException("Can not repeat String \""+input+"\" less than 0 times! count="+count);
        if(count > 0)
            internalCharSeq = input;
        this.count = count;
    }
    /**
     * CONSTRUCTOR - Strings.RepeatingCharSequence
     * @param input CharSequence to repeat
     * @param count Repeat-Count
     * @param separator Separator-Sequence to use
     */
    public RepeatingCharSequence(CharSequence input, int count, CharSequence separator) {
        this(input, count);
        this.separator = separator;
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        checkBounds(start);
        checkBounds(end);
        int subLen = end - start;
        if (subLen < 0) {
            throw new IndexOutOfBoundsException("Illegal subSequence-Length: "+subLen);
        }
        return (start == 0 && end == length()) ? this
                    : toString().substring(start, subLen);
    }
    @Override
    public int length() {
        //We return the total length of our CharSequences with the separator 1 time less than amount of repeats:
        return count < 1 ? 0
                : ( (internalCharSeq.length()*count) + (separator.length()*(count-1)));
    }
    @Override
    public char charAt(int index) {
        final int internalIndex = internalIndex(index);
        //Delegate to Separator-CharSequence or Input-CharSequence depending on internal index:
        if(internalIndex > internalCharSeq.length()-1) {
            return separator.charAt(internalIndex-internalCharSeq.length());
        }
        return internalCharSeq.charAt(internalIndex);
    }
    @Override
    public String toString() {
        return count < 1 ? ""
                : new StringBuilder(this).toString();
    }

    private void checkBounds(int index) {
        if(index < 0 || index >= length())
            throw new IndexOutOfBoundsException("Index out of Bounds: "+index);
    }
    private int internalIndex(int index) {
        // We need to add 1 Separator-Length to total length before dividing,
        // as we subtracted one Separator-Length in "length()"
        return index % ((length()+separator.length())/count);
    }
}

Ejemplo de uso:

public static void main(String[] args) {
    //String input = "12345";
    //StringBuffer input = new StringBuffer("12345");
    StringBuilder input = new StringBuilder("123");
    //String separator = "<=>";
    StringBuilder separator = new StringBuilder("<=");//.append('>');
    int repeatCount = 2;

    CharSequence repSeq = new RepeatingCharSequence(input, repeatCount, separator);
    String repStr = repSeq.toString();

    System.out.println("Repeat="+repeatCount+"\tSeparator="+separator+"\tInput="+input+"\tLength="+input.length());
    System.out.println("CharSeq:\tLength="+repSeq.length()+"\tVal="+repSeq);
    System.out.println("String :\tLength="+repStr.length()+"\tVal="+repStr);

    //Here comes the Magic with a StringBuilder as Input, as you can append to the String-Builder
    //and at the same Time your Repeating-Sequence's toString()-Method returns the updated String :)
    input.append("ff");
    System.out.println(repSeq);
    //Same can be done with the Separator:
    separator.append("===").append('>');
    System.out.println(repSeq);
}

Ejemplo de salida:

Repeat=2    Separator=<=    Input=123   Length=3
CharSeq:    Length=8    Val=123<=123
String :    Length=8    Val=123<=123
123ff<=123ff
123ff<====>123ff



En aras de la legibilidad y la portabilidad:

public String repeat(String str, int count){
    if(count <= 0) {return "";}
    return new String(new char[count]).replace("\0", str);
}



No es el más corto, pero (creo) la forma más rápida es usar StringBuilder:

 /**
   * Repeat a String as many times you need.
   *
   * @param i - Number of Repeating the String.
   * @param s - The String wich you want repeated.
   * @return The string n - times.
   */
  public static String repeate(int i, String s) {
    StringBuilder sb = new StringBuilder();
    for (int j = 0; j < i; j++)
      sb.append(s);
    return sb.toString();
  }



Realmente disfruto esta pregunta. Hay mucho conocimiento y estilos. Así que no puedo dejarlo sin mostrar mi rock and roll;)

{
    String string = repeat("1234567890", 4);
    System.out.println(string);
    System.out.println("=======");
    repeatWithoutCopySample(string, 100000);
    System.out.println(string);// This take time, try it without printing
    System.out.println(string.length());
}

/**
 * The core of the task.
 */
@SuppressWarnings("AssignmentToMethodParameter")
public static char[] repeat(char[] sample, int times) {
    char[] r = new char[sample.length * times];
    while (--times > -1) {
        System.arraycopy(sample, 0, r, times * sample.length, sample.length);
    }
    return r;
}

/**
 * Java classic style.
 */
public static String repeat(String sample, int times) {
    return new String(repeat(sample.toCharArray(), times));
}

/**
 * Java extreme memory style.
 */
@SuppressWarnings("UseSpecificCatch")
public static void repeatWithoutCopySample(String sample, int times) {
    try {
        Field valueStringField = String.class.getDeclaredField("value");
        valueStringField.setAccessible(true);
        valueStringField.set(sample, repeat((char[]) valueStringField.get(sample), times));
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}

¿Te gusta?




Usando la recursión, puede hacer lo siguiente (usando operadores ternarios, una línea máx):

public static final String repeat(String string, long number) {
    return number == 1 ? string : (number % 2 == 0 ? repeat(string + string, number / 2) : string + repeat(string + string, (number - 1) / 2));
}

Lo sé, es feo y probablemente no es eficiente, ¡pero es una línea!




public static String repeat(String str, int times) {
    int length = str.length();
    int size = length * times;
    char[] c = new char[size];
    for (int i = 0; i < size; i++) {
        c[i] = str.charAt(i % length);
    }
    return new String(c);
}



Aquí está el último Stringutils.java StringUtils.java

    public static String repeat(String str, int repeat) {
    // Performance tuned for 2.0 (JDK1.4)

    if (str == null) {
        return null;
    }
    if (repeat <= 0) {
        return EMPTY;
    }
    int inputLength = str.length();
    if (repeat == 1 || inputLength == 0) {
        return str;
    }
    if (inputLength == 1 && repeat <= PAD_LIMIT) {
        return repeat(str.charAt(0), repeat);
    }

    int outputLength = inputLength * repeat;
    switch (inputLength) {
        case 1 :
            return repeat(str.charAt(0), repeat);
        case 2 :
            char ch0 = str.charAt(0);
            char ch1 = str.charAt(1);
            char[] output2 = new char[outputLength];
            for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
                output2[i] = ch0;
                output2[i + 1] = ch1;
            }
            return new String(output2);
        default :
            StringBuilder buf = new StringBuilder(outputLength);
            for (int i = 0; i < repeat; i++) {
                buf.append(str);
            }
            return buf.toString();
    }
    }

ni siquiera necesita ser tan grande, se puede convertir en esto, y se puede copiar y pegar en una clase de utilidad en su proyecto.

    public static String repeat(String str, int num) {
    int len = num * str.length();
    StringBuilder sb = new StringBuilder(len);
    for (int i = 0; i < times; i++) {
        sb.append(str);
    }
    return sb.toString();
    }

Entonces, e5, creo que la mejor manera de hacer esto sería simplemente usar el código mencionado anteriormente, o cualquiera de las respuestas aquí. Pero el lenguaje común es demasiado grande si se trata de un proyecto pequeño.




repeated = str + str + str;

A veces lo simple es lo mejor. Todos los que lean el código pueden ver lo que está pasando.

Y el compilador hará las cosas elegantes con StringBuilderdetrás de escena para ti.




Related


Tags

java   string