Java: função para matrizes como o join () do PHP?

Respostas:

307

A partir do Java8 , é possível usar String.join().

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

Gera:

Hello, World, !

Caso contrário, o Apache Commons Lang tem uma StringUtilsclasse que possui uma joinfunção que unirá matrizes para criar a String.

Por exemplo:

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

Gera o seguinte String:

Hello, World, !
coobird
fonte
7
Para o benefício das pessoas que buscam essa resposta, provavelmente deve-se notar que isso também é o equivalente a uma associação ao Perl.
den-k
3
ele diz que está indefinido para mim
Ninjaxor
@Ninjaxor 1. commons-lang * jar deve estar no caminho de classe 2. import org.apache.commons.lang3.StringUtils;
peterh - Restabelece Monica
9
Eu recomendo que você edite esta resposta para anexar uma referência ao novo String.join()método introduzido no Java 8. Dessa forma, o grande número de pessoas que lêem essa resposta aceita se beneficiará desse conhecimento. Atualmente, o mais votado resposta mencionar este fato é bastante perdido abaixo ...
Duncan Jones
1
Vale ressaltar que String.join()funcionaria apenas para List<CharSequence>ou CharSequence[]elementos.
Enigo
71

Se você estava procurando o que usar no Android, é:

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

por exemplo:

String joined = TextUtils.join(";", MyStringArray);
Noé
fonte
2
Essa é claramente a melhor resposta para todas as versões do Android, já que o Java 8 só será lançado no Android daqui a pouco. Esta solução usa as bibliotecas Android integradas, em vez dessas soluções tolas "incluem uma enorme biblioteca para executar uma ação".
LukeStoneHm
Em setembro de 2017, o Java 8 para Android ainda está longe. Obrigado por esta resposta!
Aenadon
53

Você poderia escrever facilmente essa função em cerca de dez linhas 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();
}
Jay
fonte
35
Boas práticas para você ... não existe um padrão universal para essas coisas.
Phoebus 04/10/09
24
Mas se eu incluísse chaves, isso acrescentaria mais duas linhas de código, e eu não poderia ter afirmado ter feito isso em 11 linhas!
Jay
8
o problema é quando você, depois de um tempo, ou outra pessoa, com pressa, adiciona outra linha àquela se / para sem adicionar chaves; ou delete return null depois de if (k == 0), que em alguns casos seria compilado, mas estará incorreto. Então é melhor sacrificar uma linha extra para essa chave de fechamento (a abertura pode permanecer na mesma se / para a linha).
milan
16
Eu acho incrível que, embora a maioria das linguagens inclua essa funcionalidade em seu núcleo, a comunidade Java incentive todos a reinventar a roda.
John Strickler
33
11 linhas? Bah! Eu posso fazer isso em 1! Simplesmente remova todos os caracteres de nova linha no arquivo de origem.
Thomas Eding
25

Um pequeno mod em vez 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
fonte
Votou porque você não precisa adicionar nenhuma biblioteca.
givanse
10
Linha 7: É melhor usar .append()duas vezes para cada um em Stringvez de concatená-las e depois anexá-las ao construtor.
precisa
18

Como com muitas perguntas recentemente, o Java 8 para o resgate:


O Java 8 adicionou um novo método estático ao java.lang.Stringqual faz exatamente o que você deseja:

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

Usando isso:

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

Resulta em:

"Hello, World, !"
icza
fonte
14

A biblioteca do Google goiaba também possui esse tipo de capacidade . Você pode ver o exemplo String [] também na API.

Como já descrito na API, tenha cuidado com a imutabilidade dos métodos do construtor.

Ele pode aceitar uma variedade de objetos para funcionar no seu caso. Na minha experiência anterior, tentei ingressar em um Stack que é iterável e funciona bem.

Amostra de mim:

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
fonte
9

Dado:

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

Então, como uma alternativa à resposta de coobird, onde a cola é ",":

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

Ou para concatenar com uma sequência diferente, como "& amp;".

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

No entanto ... este funciona SOMENTE se você souber que os valores na matriz ou na lista NÃO contêm a cadeia de caracteres ",".

Rob na TVSeries.com
fonte
Arrays.asList(a).toString()trabalhou para o que eu queria fazer
Solomon Ucko
9

Se você estiver usando o Spring Framework , terá a classe StringUtils :

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

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

Não no núcleo, não. Uma pesquisa por "cola de cadeia de junção de matriz java" fornecerá alguns trechos de código sobre como conseguir isso.

por exemplo

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();
}

fonte
2
Use StringBuilder (não seguro para threads) no lugar de StringBuffer (seguro para threads) para obter melhor desempenho. A interface é a mesma.
Asaph
2
Parece ser de snippets.dzone.com/posts/show/91 . Os comentários sugerem uma versão muito melhorada: junção estática pública de String (Iterável <? Estende Objeto> pColl, separador de String) {Iterador <? estende Object> oIter; if (pColl == null || (! (oIter = pColl.iterator ()) .hasNext ())) return ""; StringBuilder oBuilder = novo StringBuilder (String.valueOf (oIter.next ())); while (oIter.hasNext ()) oBuilder.append (separador) .append (oIter.next ()); retornar oBuilder.toString (); }
Quantum7 17/03/10
6

Se você chegou aqui procurando uma conversão rápida de matriz para string, tente Arrays.toString () .

Cria uma representação String do Object[]passado. O resultado é cercado por colchetes ( "[]"), cada elemento é convertido em uma String por meio de String.valueOf(Object)e separado por ", ". Se a matriz for null, então "null"será retornado.

quietmint
fonte
MUITO OBRIGADO! As strings são separadas por "," e a coisa toda tem "[]" ao redor, o que é bom para mim.
John Henckel
5

Apenas para o desafio "Eu tenho o menor" , aqui estão as 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
fonte
2
A versão recursiva é elegante. Definitivamente vou usar isso.
Pete
A versão recursiva pode ser elegante, mas ineficiente para matrizes grandes (" copyOfRange()").
Ogre Psalm33
4

Nada embutido que eu conheça.

O Apache Commons Lang tem uma classe chamada StringUtilsque contém muitas funções de junção.

JonMR
fonte
4

É assim que eu faço.

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
fonte
2

Uma alternativa semelhante

/**
 * @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
fonte
2

Minha rotação.

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
fonte
1

Você gosta do meu caminho de 3 linhas usando apenas os métodos da classe 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
fonte
1
Não é para ser eficiente. Use StringBuilderse você precisar de eficiência: P
Ryoichiro Oka
0

Para obter "str1, str2" de "str1", "str2", "":

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

Além disso, você pode adicionar verificação nula extra

ema
fonte
0

Caso você esteja usando a biblioteca Java Funcional e, por algum motivo, não possa usar o Streams do Java 8 (que pode ser o caso ao usar o plug-in Android + Retrolambda), aqui está uma solução funcional para você:

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

Observe que não é a abordagem mais eficiente, mas funciona bem para pequenas listas.

Dmitry Zaytsev
fonte
-1

Eu faço dessa maneira usando um 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
fonte
1
s + delimiter(concatenação de cadeia de caracteres com o operador mais) anula todo o objetivo de usar a StringBuilder.
quietmint
Além disso, essa abordagem significaria que uma matriz como: {"foo", "bar"} com o delimitador ":" seria transformada em "foo: bar:"
pioto
-2

Existe uma técnica simples de taquigrafia que uso na maioria das vezes.

String op = new String;
for (int i : is) 
{
    op += candidatesArr[i-1]+",";
}
op = op.substring(0, op.length()-1);
Gaurav Adurkar
fonte
Isso funciona apenas com delimitadores de comprimento 1 e requer 'números mágicos' (embora bastante locais) se você quiser um delimitador de comprimento diferente.
Mai13
Você pode adicionar vários personagens enquanto anexando
Gaurav Adurkar
do que simplesmente: op = op.substring (0, op.length () - ",". length ()); qual é o grande problema?
Dennis
-3

java.util.Arrays possui um método 'asList'. Juntamente com a API java.util.List / ArrayList, você fornece tudo o que você precisa :;

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
fonte
7
A questão é como unir uma matriz de cadeias com um delimitador, não como unir duas matrizes de cadeias.
toolbear