Eliminar el último carácter de un StringBuilder?


Cuando tiene que recorrer una colección y hacer una cadena de cada dato separada por un delimitador, siempre termina con un delimitador adicional al final, por ejemplo,

for(String serverId : serverIds) {
 sb.append(serverId);
 sb.append(",");
}

Da algo como : serverId_1, serverId_2, serverId_3,

Me gustaría eliminar el último carácter en el StringBuilder (sin convertirlo porque todavía lo necesito después de este bucle).

Author: skaffman, 2010-08-03

16 answers

Otros han señalado el método deleteCharAt, pero aquí hay otro enfoque alternativo:

String prefix = "";
for (String serverId : serverIds) {
  sb.append(prefix);
  prefix = ",";
  sb.append(serverId);
}

Como alternativa, utilice el Joiner clase de Guayaba :)

A partir de Java 8, StringJoiner es parte del estándar JRE.

 513
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-14 03:48:40

Otra solución simple es:

sb.setLength(sb.length() - 1);

Una solución más complicada:

La solución anterior asume que sb.length() > 0... es decir, hay un" último carácter " para eliminar. Si no puede hacer esa suposición, y/o no puede tratar con la excepción que se produciría si la suposición es incorrecta, entonces verifique primero la longitud del constructor de cadenas; por ejemplo,

// Readable version
if (sb.length() > 0) {
   sb.setLength(sb.length() - 1);
}

O

// Concise but harder-to-read version of the above.
sb.setLength(Math.max(sb.length() - 1, 0));
 323
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-20 22:45:21
sb.deleteCharAt(sb.length() - 1) 
 129
Author: bragboy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-07 20:37:45

A partir de Java 8, la clase String tiene un método estáticojoin. El primer argumento es una cadena que desea entre cada par de cadenas, y el segundo es un Iterable<CharSequence> (que son ambas interfaces, por lo que algo como List<String> funciona. Así que puedes hacer esto:

String.join(",", serverIds);

También en Java 8, podría utilizar el nuevo StringJoiner class, para escenarios en los que desea comenzar a construir la cadena antes de tener la lista completa de elementos para poner en ella.

 51
Author: ArtOfWarfare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-18 13:10:04

En este caso,

sb.setLength(sb.length() - 1);

Es preferible ya que solo asigna el último valor a '\0' mientras que eliminar el último carácter hace System.arraycopy

 33
Author: Rohit Reddy Korrapolu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-12 20:13:20

Simplemente obtenga la posición de la última ocurrencia de caracteres.

for(String serverId : serverIds) {
 sb.append(serverId);
 sb.append(",");
}
sb.deleteCharAt(sb.lastIndexOf(","));

Dado que lastIndexOf realizará una búsqueda inversa, y usted sabe que encontrará en el primer intento, el rendimiento no será un problema aquí.

 24
Author: Reuel Ribeiro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-13 13:54:25

Otra alternativa

for(String serverId : serverIds) {
   sb.append(",");
   sb.append(serverId); 
}
sb.deleteCharAt(0);
 10
Author: Rafiq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-02 23:23:40

Con Java-8 puede usar el método estático de la clase String,

String#join(CharSequence delimiter,Iterable<? extends CharSequence> elements).


public class Test {

    public static void main(String[] args) {

        List<String> names = new ArrayList<>();
        names.add("James");
        names.add("Harry");
        names.add("Roy");
        System.out.println(String.join(",", names));
    }
}

SALIDA

James,Harry,Roy
 10
Author: coder-croc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-27 04:29:48

Alternativamente,

StringBuilder result = new StringBuilder();
for(String string : collection) {
    result.append(string);
    result.append(',');
}
return result.substring(0, result.length() - 1) ;
 6
Author: Zaki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-11 09:22:31
StringBuilder sb = new StringBuilder();
sb.append("abcdef");
sb.deleteCharAt(sb.length() - 1);
assertEquals("abcde",sb.toString());
// true
 5
Author: Antoine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-10 07:57:51

Otra alternativa:

public String join(Collection<String> collection, String seperator) {
    if (collection.isEmpty()) return "";

    Iterator<String> iter = collection.iterator();
    StringBuilder sb = new StringBuilder(iter.next());
    while (iter.hasNext()) {
        sb.append(seperator);
        sb.append(iter.next());
    }

    return sb.toString();
}
 3
Author: Jason Day,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-03 11:33:07

Para evitar reinit(afectar el rendimiento) de prefix use TextUtils.isEmpty:

            String prefix = "";
            for (String item : list) {
                sb.append(prefix);
                if (TextUtils.isEmpty(prefix))
                    prefix = ",";
                sb.append(item);
            }
 2
Author: NickUnuchek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-26 09:14:07

Personalmente me gusta añadir un carácter de retroceso (o más para un "delimitador" más largo) al final:

for(String serverId : serverIds) {
    sb.append(serverId);
    sb.append(",");
}

sb.append('\b');

Tenga en cuenta que tiene problemas:

  • cómo se muestra \b depende del entorno,
  • el length() del contenido String puede ser diferente de la longitud de los caracteres "visibles"

Cuando \b se ve bien y la longitud no importa, como iniciar sesión en una consola, esto me parece lo suficientemente bueno.

 1
Author: Attacktive,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 03:02:51

Puede intentar usar la clase 'Joiner' en lugar de eliminar el último carácter de su texto generado;

                List<String> textList = new ArrayList<>();
                textList.add("text1");
                textList.add("text2");
                textList.add("text3");

                Joiner joiner = Joiner.on(",").useForNull("null");
                String output = joiner.join(textList);

               //output : "text1,text2,text3"
 0
Author: oguzhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-01 13:59:25

Aquí hay otra solución:

for(String serverId : serverIds) {
   sb.append(",");
   sb.append(serverId); 
}

String resultingString = "";
if ( sb.length() > 1 ) {
    resultingString = sb.substring(1);
}
 0
Author: Stephan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-22 11:53:39

Estoy haciendo algo como a continuación:

    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < value.length; i++) {
        stringBuilder.append(values[i]);
        if (value.length-1) {
            stringBuilder.append(", ");
        }
    }
 0
Author: VicJordan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-22 01:52:03