Java: ¿función para matrices como join () de PHP?

Respuestas:

307

A partir de Java8 es posible usarlo String.join().

String.join(", ", new String[]{"Hello", "World", "!"})

Genera:

Hello, World, !

De lo contrario, Apache Commons Lang tiene una StringUtilsclase que tiene una joinfunción que unirá matrices para crear un String.

Por ejemplo:

StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")

Genera lo siguiente String:

Hello, World, !
Coobird
fuente
77
Para el beneficio de las personas que buscan esta respuesta, probablemente debería tenerse en cuenta que esto también es el equivalente de una unión Perl.
k-den
3
dice que no está definido para mí
Ninjaxor
@Ninjaxor 1. commons-lang * jar debe estar en classpath 2. import org.apache.commons.lang3.StringUtils;
peterh - Restablece a Mónica el
9
Le recomendaría que edite esta respuesta para agregar una referencia al nuevo String.join()método introducido en Java 8. De esta manera, el gran número de personas que leen esta respuesta aceptada se beneficiarán de ese conocimiento. Actualmente, la respuesta más votada que menciona este hecho se pierde bastante abajo ...
Duncan Jones
1
Vale la pena mencionar que String.join()funcionaría solo para List<CharSequence>o CharSequence[]elementos.
Enigo
71

Si estabas buscando qué usar en Android, es:

String android.text.TextUtils.join(CharSequence delimiter, Object[] tokens)

por ejemplo:

String joined = TextUtils.join(";", MyStringArray);
Noé
fuente
2
Esta es claramente la mejor respuesta para todas las versiones de Android, ya que Java 8 solo se lanzará en Android en un momento. Esta solución utiliza las bibliotecas de Android integradas, en lugar de estas soluciones tontas de "incluir una gran biblioteca para realizar una acción".
LukeStoneHm
Es septiembre de 2017, Java 8 para Android todavía está muy lejos. Gracias por esta respuesta!
Aenadon
53

Podría escribir fácilmente una función de este tipo en aproximadamente diez líneas de código:

String combine(String[] s, String glue)
{
  int k = s.length;
  if ( k == 0 )
  {
    return null;
  }
  StringBuilder out = new StringBuilder();
  out.append( s[0] );
  for ( int x=1; x < k; ++x )
  {
    out.append(glue).append(s[x]);
  }
  return out.toString();
}
Arrendajo
fuente
35
Buena práctica según usted ... no existe un estándar universal para tales cosas.
phoebus
24
Pero si incluyera llaves, eso habría agregado dos líneas más de código, ¡y no podría haber afirmado haberlo hecho en 11 líneas!
Jay
8
el problema es cuando después de un tiempo, o alguien más, tiene prisa, agrega otra línea a eso si / para sin agregar llaves; o eliminar return null después de if (k == 0), que en algunos casos se compilaría pero será incorrecto. Entonces es mejor sacrificar una línea extra por esa llave de cierre (la abertura puede permanecer en la misma línea si / por).
Milán
16
Creo que es increíble que, si bien la mayoría de los idiomas incorporan dicha funcionalidad en su núcleo, la comunidad Java alienta a todos a reinventar la rueda.
John Strickler
33
11 líneas? ¡Bah! ¡Puedo hacerlo en 1! Simplemente elimine todos los caracteres de nueva línea en el archivo fuente.
Thomas Eding
25

Un pequeño mod en lugar de usar substring ():

//join(String array,delimiter)
public static String join(String r[],String d)
{
        if (r.length == 0) return "";
        StringBuilder sb = new StringBuilder();
        int i;
        for(i=0;i<r.length-1;i++){
            sb.append(r[i]);
            sb.append(d);
        }
        sb.append(r[i]);
        return sb.toString();
}
everlasto
fuente
Votado porque no necesita agregar ninguna biblioteca.
givanse
10
Línea 7: ¿Es mejor si se usa .append()dos veces para cada uno en Stringlugar de concatenarlos y luego agregarlos al generador?
Talha Ahmed Khan
18

Como con muchas preguntas últimamente, Java 8 al rescate:


Java 8 agregó un nuevo método estático al java.lang.Stringque hace exactamente lo que quieres:

public static String join(CharSequence delimeter, CharSequence... elements);

Utilizándolo:

String s = String.join(", ", new String[] {"Hello", "World", "!"});

Resultados en:

"Hello, World, !"
icza
fuente
14

La biblioteca de guayaba de Google también tiene este tipo de capacidad . Puede ver el ejemplo de Cadena [] también desde la API.

Como ya se describió en la api, tenga cuidado con la inmutabilidad de los métodos de construcción.

Puede aceptar una variedad de objetos para que funcione en su caso. En mi experiencia anterior, intenté unirme a una pila que es iterable y funciona bien.

Muestra de mí:

Deque<String> nameStack = new ArrayDeque<>();
nameStack.push("a coder");
nameStack.push("i am");
System.out.println("|" + Joiner.on(' ').skipNulls().join(nameStack) + "|");

imprime: |i am a coder|

bertie
fuente
9

Dado:

String[] a = new String[] { "Hello", "World", "!" };

Luego, como alternativa a la respuesta de Coobird, donde el pegamento es ",":

Arrays.asList(a).toString().replaceAll("^\\[|\\]$", "")

O para concatenar con una cadena diferente, como "& amp;".

Arrays.asList(a).toString().replaceAll(", ", " &amp; ").replaceAll("^\\[|\\]$", "")

Sin embargo ... este SOLO funciona si sabe que los valores en la matriz o lista NO contienen la cadena de caracteres ",".

Rob en TVSeries.com
fuente
Arrays.asList(a).toString()trabajó para lo que quería hacer
Solomon Ucko
9

Si está utilizando Spring Framework, entonces tiene la clase StringUtils :

import static org.springframework.util.StringUtils.arrayToDelimitedString;

arrayToDelimitedString(new String[] {"A", "B", "C"}, "\n");
devstopfix
fuente
8

No en el núcleo, no. Sin embargo, la búsqueda de "java array join string glue" le dará algunos fragmentos de código sobre cómo lograr esto.

p.ej

public static String join(Collection s, String delimiter) {
    StringBuffer buffer = new StringBuffer();
    Iterator iter = s.iterator();
    while (iter.hasNext()) {
        buffer.append(iter.next());
        if (iter.hasNext()) {
            buffer.append(delimiter);
        }
    }
    return buffer.toString();
}

fuente
2
Utilice StringBuilder (no apto para subprocesos) en lugar de StringBuffer (seguro para subprocesos) para un mejor rendimiento. La interfaz es la misma.
Asaph
2
Esto parece ser de snippets.dzone.com/posts/show/91 . Los comentarios sugieren una versión muy mejorada: unión de cadena estática pública (Iterable <? Extend Object> pColl, String separator) {Iterator <? extiende Object> oIter; if (pColl == null || (! (oIter = pColl.iterator ()) .hasNext ())) return ""; StringBuilder oBuilder = new StringBuilder (String.valueOf (oIter.next ())); while (oIter.hasNext ()) oBuilder.append (separador) .append (oIter.next ()); return oBuilder.toString (); }
Quantum7
6

Si aterrizó aquí buscando una conversión rápida de matriz a cadena, pruebe Arrays.toString () .

Crea una representación de cadena del Object[]pasado. El resultado está rodeado de corchetes ( "[]"), cada elemento se convierte en una Cadena a través de String.valueOf(Object)y se separa por ", ". Si la matriz es null, entonces "null"se devuelve.

quietmint
fuente
¡MUCHAS GRACIAS! Las cadenas están separadas por "," y todo tiene "[]" alrededor, lo cual está bien para mí.
John Henckel
5

Solo por el "Tengo el más corto" desafío , aquí hay minas;)

Iterativo:

public static String join(String s, Object... a) {
    StringBuilder o = new StringBuilder();
    for (Iterator<Object> i = Arrays.asList(a).iterator(); i.hasNext();)
        o.append(i.next()).append(i.hasNext() ? s : "");
    return o.toString();
}

Recursivo:

public static String join(String s, Object... a) {
    return a.length == 0 ? "" : a[0] + (a.length == 1 ? "" : s + join(s, Arrays.copyOfRange(a, 1, a.length)));
}
sp00m
fuente
2
La versión recursiva es elegante. Definitivamente voy a usar eso.
Pete
La versión recursiva puede ser elegante, pero ineficiente para grandes matrices (" copyOfRange()").
Ogre Psalm33
4

Nada incorporado que yo sepa.

Apache Commons Lang tiene una clase llamada StringUtilsque contiene muchas funciones de combinación.

JonMR
fuente
4

Así es como lo hago.

private String join(String[] input, String delimiter)
{
    StringBuilder sb = new StringBuilder();
    for(String value : input)
    {
        sb.append(value);
        sb.append(delimiter);
    }
    int length = sb.length();
    if(length > 0)
    {
        // Remove the extra delimiter
        sb.setLength(length - delimiter.length());
    }
    return sb.toString();
}
Richard Corfield
fuente
2

Una alternativa similar

/**
 * @param delimiter 
 * @param inStr
 * @return String
 */
public static String join(String delimiter, String... inStr)
{
    StringBuilder sb = new StringBuilder();
    if (inStr.length > 0)
    {
        sb.append(inStr[0]);
        for (int i = 1; i < inStr.length; i++)
        {
            sb.append(delimiter);                   
            sb.append(inStr[i]);
        }
    }
    return sb.toString();
}
William Simpson
fuente
2

Mi giro

public static String join(Object[] objects, String delimiter) {
  if (objects.length == 0) {
    return "";
  }
  int capacityGuess = (objects.length * objects[0].toString().length())
      + ((objects.length - 1) * delimiter.length());
  StringBuilder ret = new StringBuilder(capacityGuess);
  ret.append(objects[0]);
  for (int i = 1; i < objects.length; i++) {
    ret.append(delimiter);
    ret.append(objects[i]);
  }
  return ret.toString();
}

public static String join(Object... objects) {
  return join(objects, "");
}
Jackson
fuente
1

¿Te gusta mi forma de 3 líneas usando solo los métodos de la clase String?

static String join(String glue, String[] array) {
    String line = "";
    for (String s : array) line += s + glue;
    return (array.length == 0) ? line : line.substring(0, line.length() - glue.length());
}
Ryoichiro Oka
fuente
1
No está destinado a ser eficiente. Úselo StringBuildersi necesita eficiencia: P
Ryoichiro Oka
0

Para obtener "str1, str2" de "str1", "str2", "":

Stream.of("str1", "str2", "").filter(str -> !str.isEmpty()).collect(Collectors.joining(", ")); 

También puede agregar cheque nulo adicional

ema
fuente
0

En caso de que esté usando la biblioteca funcional de Java y por alguna razón no pueda usar Streams de Java 8 (que podría ser el caso al usar el complemento Android + Retrolambda), aquí hay una solución funcional para usted:

String joinWithSeparator(List<String> items, String separator) {
    return items
            .bind(id -> list(separator, id))
            .drop(1)
            .foldLeft(
                    (result, item) -> result + item,
                    ""
            );
}

Tenga en cuenta que no es el enfoque más eficiente, pero funciona bien para listas pequeñas.

Dmitry Zaytsev
fuente
-1

Lo hago de esta manera usando un StringBuilder:

public static String join(String[] source, String delimiter) {
    if ((null == source) || (source.length < 1)) {
        return "";
    }

    StringBuilder stringbuilder = new StringBuilder();
    for (String s : source) {
        stringbuilder.append(s + delimiter);
    }
    return stringbuilder.toString();
} // join((String[], String)
spanky762
fuente
1
s + delimiter(concatenación de cadenas con el operador más) anula el propósito de usar a StringBuilder.
quietmint
Además, este enfoque significaría que una matriz como: {"foo", "bar"} con delimitador ":" se convertiría en "foo: bar:"
pioto
-2

Hay una técnica simple de taquigrafía que uso la mayoría de las veces.

String op = new String;
for (int i : is) 
{
    op += candidatesArr[i-1]+",";
}
op = op.substring(0, op.length()-1);
Gaurav Adurkar
fuente
Esto solo funciona con delimitadores de longitud 1 y requiere 'números mágicos' (aunque bastante locales) si desea un delimitador de una longitud diferente.
maiwald
Puedes agregar varios personajes mientras
agregas
que simplemente hacer: op = op.substring (0, op.length () - ",". length ()); ¿Cual es el problema?
Dennis
-3

java.util.Arrays tiene un método 'asList'. Junto con la API java.util.List / ArrayList, esto le brinda todo lo que necesita :;

private static String[] join(String[] array1, String[] array2) {

    List<String> list = new ArrayList<String>(Arrays.asList(array1));
    list.addAll(Arrays.asList(array2));
    return list.toArray(new String[0]);
}
Adriaan Koster
fuente
77
La pregunta es cómo unir un conjunto de cadenas con un delimitador, no cómo unir dos conjuntos de cadenas.
toolbear