Enquanto trabalhava em um aplicativo Java, recentemente precisei montar uma lista de valores delimitada por vírgulas para passar para outro serviço da web sem saber quantos elementos haveria com antecedência. O melhor que eu conseguia pensar era algo assim:
public String appendWithDelimiter( String original, String addition, String delimiter ) {
if ( original.equals( "" ) ) {
return addition;
} else {
return original + delimiter + addition;
}
}
String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );
Sei que isso não é particularmente eficiente, já que existem strings sendo criadas em todo o lugar, mas eu estava buscando mais clareza do que otimização.
Em Ruby, eu posso fazer algo assim, que parece muito mais elegante:
parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");
Mas como o Java não possui um comando join, não consegui descobrir nada equivalente.
Então, qual é a melhor maneira de fazer isso em Java?
Respostas:
Antes do Java 8:
O commons lang do Apache é seu amigo aqui - ele fornece um método de junção muito semelhante ao que você se refere no Ruby:
StringUtils.join(java.lang.Iterable,char)
Java 8:
O Java 8 fornece a junção imediata através de
StringJoiner
eString.join()
. Os trechos abaixo mostram como você pode usá-los:StringJoiner
String.join(CharSequence delimiter, CharSequence... elements))
String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
fonte
Você pode escrever um pequeno método utilitário de estilo de junção que funciona em java.util.Lists
Em seguida, use-o assim:
fonte
List<String>
no seu inicializadorIterator<?>
e ter o mesmo efeito?No caso do Android, a classe StringUtils de commons não está disponível, então, para isso, usei
http://developer.android.com/reference/android/text/TextUtils.html
fonte
A biblioteca Guava do Google possui a classe com.google.common.base.Joiner, que ajuda a resolver essas tarefas.
Amostras:
Aqui está um artigo sobre os utilitários de string do Guava .
fonte
No Java 8, você pode usar
String.join()
:Veja também esta resposta para obter um exemplo da API de fluxo.
fonte
Você pode generalizá-lo, mas não há junção em Java, como você bem diz.
Isso pode funcionar melhor.
fonte
Iterable<String>
e apenas use o fato de que você pode iterar sobre ele. No seu exemplo, você não precisa do número de itens da coleção, portanto isso é ainda mais geral.StringBuilder
vez disso. Eles são idênticos, excetoStringBuffer
fornecem segurança desnecessária da linha. Alguém pode editá-lo!isEmpty()
método, use onext()
métodoNo Java 8, você pode fazer o seguinte:
se a lista tiver nulos, você pode usar:
também suporta prefixo e sufixo:
fonte
Use uma abordagem baseada em
java.lang.StringBuilder
! ("Uma sequência mutável de caracteres.")Como você mencionou, todas essas concatenações de strings estão criando Strings por todo o lado.
StringBuilder
não vai fazer isso.Por que ao
StringBuilder
invés deStringBuffer
? DoStringBuilder
javadoc:fonte
Eu usaria o Google Collections. Há uma boa instalação de associação.
http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/base/Join.html
Mas se eu quisesse escrever sozinho,
Eu acho que funciona melhor com uma coleção de objetos, já que agora você não precisa converter seus objetos em seqüências de caracteres antes de se juntar a eles.
fonte
A classe StringUtils do Apache commons possui um método de junção.
fonte
Java 8
fonte
Você pode usar o
StringBuilder
tipo de Java para isso. Também existeStringBuffer
, mas contém uma lógica de segurança de thread extra que geralmente é desnecessária.fonte
E um mínimo (se você não quiser incluir o Apache Commons ou o Gauva nas dependências do projeto apenas para unir cadeias)
fonte
Use StringBuilder e classe
Separator
O separador envolve um delimitador. O delimitador é retornado pelo
toString
método Separator , a menos que na primeira chamada que retorne a string vazia!Código fonte da classe
Separator
fonte
Separator
tal modificar para usar um emStringBuilder
vez de concatenarStrings
?Separator
apenas retorna o delimitador, ele não concatena a própria string.Separator
??? Por que não usar apenas uma string simples ..?!Por que não escrever seu próprio método join ()? Seria tomada como parâmetros a coleção de Strings e um delimitador String. Dentro do método, itere sobre a coleção e crie seu resultado em um StringBuffer.
fonte
Se você estiver usando o Spring MVC, poderá tentar as seguintes etapas.
Isso resultará em
a,b,c
fonte
Se você estiver usando o Eclipse Collections , poderá usar
makeString()
ouappendString()
.makeString()
retorna umaString
representação, semelhante atoString()
.Tem três formas
makeString(start, separator, end)
makeString(separator)
o padrão inicia e termina com cadeias vaziasmakeString()
padroniza o separador para", "
(vírgula e espaço)Exemplo de código:
appendString()
é semelhante amakeString()
, mas anexa a umAppendable
(comoStringBuilder
) e évoid
. Ele tem as mesmas três formas, com um primeiro argumento adicional, o Appendable.Se você não pode converter sua coleção em um tipo de Coleções Eclipse, basta adaptá-la com o adaptador relevante.
Nota: Sou responsável por coleções do Eclipse.
fonte
Tipo nativo Java 8
Objeto personalizado do Java 8:
fonte
Você provavelmente deve usar a
StringBuilder
com oappend
método para construir seu resultado, mas, caso contrário, essa é uma solução tão boa quanto o Java tem a oferecer.fonte
Por que você não faz em Java o mesmo que está fazendo em ruby, que é criar a sequência separada por delimitador somente depois de adicionar todas as partes à matriz?
Você pode mover esse loop for em um método auxiliar separado e também usar StringBuilder em vez de StringBuffer ...
Editar : corrigida a ordem dos anexos.
fonte
Com o Java 5 args variáveis, você não precisa inserir todas as suas strings em uma coleção ou matriz explicitamente:
fonte
Para aqueles que estão em um contexto Spring, sua classe StringUtils também é útil:
Existem muitos atalhos úteis, como:
e muitos outros.
Isso pode ser útil se você ainda não estiver usando o Java 8 e já estiver em um contexto do Spring.
Eu prefiro o Apache Commons (embora seja muito bom também) pelo suporte ao Collection, que é mais fácil assim:
fonte
Você pode tentar algo como isto:
fonte
Então, basicamente, algo como isto:
fonte
Não sei se isso realmente é melhor, mas pelo menos está usando o StringBuilder, que pode ser um pouco mais eficiente.
Abaixo, há uma abordagem mais genérica se você puder criar a lista de parâmetros ANTES de fazer qualquer delimitação de parâmetro.
fonte
Sua abordagem não é muito ruim, mas você deve usar um StringBuffer em vez de usar o sinal +. O + tem a grande desvantagem de que uma nova instância String está sendo criada para cada operação única. Quanto mais tempo sua corda ficar, maior será a sobrecarga. Portanto, usar um StringBuffer deve ser a maneira mais rápida:
Depois de terminar de criar sua string, basta chamar toString () no StringBuffer retornado.
fonte
Em vez de usar a concatenação de strings, você deve usar StringBuilder se seu código não estiver em thread e StringBuffer, se estiver.
fonte
Você está tornando isso um pouco mais complicado do que precisa ser. Vamos começar com o fim do seu exemplo:
Com a pequena alteração do uso de um StringBuilder em vez de um String, isso se torna:
Quando terminar (suponho que você também precise verificar algumas outras condições), remova a vírgula final com um comando como este:
E, finalmente, obtenha a sequência desejada
Você também pode substituir o "," na segunda chamada para anexar com uma cadeia de caracteres delimitadora genérica que pode ser definida como qualquer coisa. Se você tiver uma lista de itens que você precisa anexar (não condicionalmente), poderá colocar esse código dentro de um método que faça uma lista de strings.
fonte
fonte
Então, você pode fazer algumas coisas para ter a sensação de que está procurando:
1) Estender a classe List - e adicione o método join a ele. O método join simplesmente faria o trabalho de concatenar e adicionar o delimitador (que poderia ser um parâmetro para o método join)
2) Parece que o Java 7 adicionará métodos de extensão ao java - o que permite anexar um método específico a uma classe: para que você possa escrever esse método join e adicioná-lo como um método de extensão à List ou até ao Coleção.
A solução 1 é provavelmente a única realista, agora, já que o Java 7 ainda não foi lançado :) Mas deve funcionar muito bem.
Para usar os dois, basta adicionar todos os seus itens à Lista ou Coleção, como de costume, e chamar o novo método personalizado para 'juntá-los'.
fonte