Java: converte List para uma string

JavaScript tem Array.join()

 js>["Bill","Bob","Steve"].join(" and ") Bill and Bob and Steve 

O Java tem algo assim? Eu sei que posso remendar algo com o StringBuilder:

 static public String join(List list, String conjunction) { StringBuilder sb = new StringBuilder(); boolean first = true; for (String item : list) { if (first) first = false; else sb.append(conjunction); sb.append(item); } return sb.toString(); } 

… mas não faz sentido fazer isso se algo parecido já faz parte do JDK.

Com o Java 8, você pode fazer isso sem qualquer biblioteca de terceiros.

Se você quiser juntar-se a uma coleção de seqüências de caracteres, você pode usar o novo método String.join () :

 List list = Arrays.asList("foo", "bar", "baz"); String joined = String.join(" and ", list); // "foo and bar and baz" 

Se você tiver uma coleção com outro tipo que não seja String, poderá usar a API de stream com o Collector de associação :

 List list = Arrays.asList( new Person("John", "Smith"), new Person("Anna", "Martinez"), new Person("Paul", "Watson ") ); String joinedFirstNames = list.stream() .map(Person::getFirstName) .collect(Collectors.joining(", ")); // "John, Anna, Paul" 

A class StringJoiner também pode ser útil.

Todas as referências ao Apache Commons são boas (e é isso que a maioria das pessoas usa), mas acho que o equivalente do Guava , o Joiner , tem uma API muito mais agradável.

Você pode fazer o simples caso de junit com

 Joiner.on(" and ").join(names) 

mas também lida facilmente com nulos:

 Joiner.on(" and ").skipNulls().join(names); 

ou

 Joiner.on(" and ").useForNull("[unknown]").join(names); 

e (bastante útil, tanto quanto eu estou interessado em usá-lo de preferência para commons-lang), a capacidade de lidar com mapas:

 Map ages = .....; String foo = Joiner.on(", ").withKeyValueSeparator(" is ").join(ages); // Outputs: // Bill is 25, Joe is 30, Betty is 35 

que é extremamente útil para debugging etc.

Não fora da checkbox, mas muitas bibliotecas têm semelhantes:

Commons Lang:

 org.apache.commons.lang.StringUtils.join(list, conjunction); 

spring:

 org.springframework.util.StringUtils.collectionToDelimitedString(list, conjunction); 

No Android você pode usar a class TextUtils .

 TextUtils.join(" and ", names); 

Não, não existe esse método de conveniência na API Java padrão.

Não é de surpreender que o Apache Commons forneça tal coisa em sua class StringUtils , caso você não queira escrevê-la por conta própria.

Três possibilidades no Java 8:

 List list = Arrays.asList("Alice", "Bob", "Charlie") String result = String.join(" and ", list); result = list.stream().collect(Collectors.joining(" and ")); result = list.stream().reduce((t, u) -> t + " and " + u).orElse(""); 

Com um coletor java 8, isso pode ser feito com o seguinte código:

 Arrays.asList("Bill", "Bob", "Steve").stream() .collect(Collectors.joining(" and ")); 

Além disso, a solução mais simples no java 8:

 String.join(" and ", "Bill", "Bob", "Steve"); 

ou

 String.join(" and ", Arrays.asList("Bill", "Bob", "Steve")); 

Eu escrevi este aqui (eu uso ele para beans e explora o toString , então não escreva Collection ):

 public static String join(Collection col, String delim) { StringBuilder sb = new StringBuilder(); Iterator iter = col.iterator(); if (iter.hasNext()) sb.append(iter.next().toString()); while (iter.hasNext()) { sb.append(delim); sb.append(iter.next().toString()); } return sb.toString(); } 

mas a Collection não é suportada pelo JSP, então para o TLD eu escrevi:

 public static String join(List list, String delim) { int len = list.size(); if (len == 0) return ""; StringBuilder sb = new StringBuilder(list.get(0).toString()); for (int i = 1; i < len; i++) { sb.append(delim); sb.append(list.get(i).toString()); } return sb.toString(); } 

e colocar no arquivo .tld :

   join com.core.util.ReportUtil java.lang.String join(java.util.List, java.lang.String)   

e usá-lo em arquivos JSP como:

 <%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%> ${funnyFmt:join(books, ", ")} 

O código que você tem é o caminho certo para fazer isso se você quiser fazer usando o JDK sem nenhuma biblioteca externa. Não existe um “one-liner” simples que você possa usar no JDK.

Se você pode usar bibliotecas externas, recomendo que você procure na class org.apache.commons.lang.StringUtils na biblioteca do Apache Commons.

Um exemplo de uso:

 List list = Arrays.asList("Bill", "Bob", "Steve"); String joinedResult = StringUtils.join(list, " and "); 

Uma maneira ortodoxa de alcançá-lo é definindo uma nova function:

 public static String join(String join, String... strings) { if (strings == null || strings.length == 0) { return ""; } else if (strings.length == 1) { return strings[0]; } else { StringBuilder sb = new StringBuilder(); sb.append(strings[0]); for (int i = 1; i < strings.length; i++) { sb.append(join).append(strings[i]); } return sb.toString(); } } 

Amostra:

 String[] array = new String[] { "7, 7, 7", "Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][","~,~" }; String joined; joined = join(" and ","7, 7, 7", "Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][","~,~"); joined = join(" and ", array); // same result System.out.println(joined); 

Saída:

7, 7, 7 e Bill e Bob e Steve e [Bill] e 1,2,3 e Apple] [e ~, ~

Você pode usar a biblioteca apache commons que possui uma class StringUtils e um método de junit.

Verifique este link: https://commons.apache.org/proper/commons-lang/javadocs/api.2.0/org/apache/commons/lang/StringUtils.html

Note que o link acima pode se tornar obsoleto ao longo do tempo, caso em que você pode apenas pesquisar na web por “apache commons StringUtils”, que deve permitir que você encontre a referência mais recente.

(referenciada a partir desta discussão) Java equivalentes de C # String.Format () e String.Join ()

Solução Java 8 com java.util.StringJoiner

O Java 8 tem uma class StringJoiner . Mas você ainda precisa escrever um pouco de clichê, porque é Java.

 StringJoiner sj = new StringJoiner(" and ", "" , ""); String[] names = {"Bill", "Bob", "Steve"}; for (String name : names) { sj.add(name); } System.out.println(sj); 

Você consegue fazer isso:

 String aToString = java.util.Arrays.toString(anArray); // Do not need to do this if you are OK with '[' and ']' aToString = aToString.substring(1, aToString.length() - 1); 

Ou um one-liner (somente quando você não quer ‘[‘ e ‘]’)

 String aToString = java.util.Arrays.toString(anArray).substring(1).replaceAll("\\]$", ""); 

Espero que isto ajude.

Uma maneira divertida de fazer isso com o JDK puro, em uma linha de serviço:

 String[] array = new String[] { "Bill", "Bob", "Steve","[Bill]","1,2,3","Apple ][" }; String join = " and "; String joined = Arrays.toString(array).replaceAll(", ", join) .replaceAll("(^\\[)|(\\]$)", ""); System.out.println(joined); 

Saída:

Bill e Bob e Steve e [Bill] e 1,2,3 e Apple] [


Uma maneira não muito perfeita e não muito divertida!

 String[] array = new String[] { "7, 7, 7","Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][" }; String join = " and "; for (int i = 0; i < array.length; i++) array[i] = array[i].replaceAll(", ", "~,~"); String joined = Arrays.toString(array).replaceAll(", ", join) .replaceAll("(^\\[)|(\\]$)", "").replaceAll("~,~", ", "); System.out.println(joined); 

Saída:

7, 7, 7 e Bill e Bob e Steve e [Bill] e 1,2,3 e Apple] [

Você pode querer experimentar o método de associação do Apache Commons StringUtils:

http://commons.apache.org/lang/api/org/apache/commons/lang/StringUtils.html#join(java.util.Iterator , java.lang.String)

Eu descobri que o Apache StringUtils pega a folga do jdk 😉

Se você estiver usando o Eclipse Collections (anteriormente GS Collections ), você pode usar o método makeString() .

 List list = Arrays.asList("Bill", "Bob", "Steve"); String string = ListAdapter.adapt(list).makeString(" and "); Assert.assertEquals("Bill and Bob and Steve", string); 

Se você pode converter sua List em um tipo de collections Eclipse, então você pode se livrar do adaptador.

 MutableList list = Lists.mutable.with("Bill", "Bob", "Steve"); String string = list.makeString(" and "); 

Se você quer apenas uma string separada por vírgula, pode usar a versão de makeString() que não usa parâmetros.

 Assert.assertEquals( "Bill, Bob, Steve", Lists.mutable.with("Bill", "Bob", "Steve").makeString()); 

Nota: Eu sou um committer para collections do Eclipse.

A API Guava do Google também possui .join (), embora (como deveria ser óbvio com as outras respostas), o Apache Commons é praticamente o padrão aqui.

EDITAR

Eu também noto o problema subjacente da implementação toString() e sobre o elemento que contém o separador, mas achei que estava sendo paranóico.

Desde que eu tenho dois comentários sobre isso, estou mudando minha resposta para:

  static String join( List list , String replacement ) { StringBuilder b = new StringBuilder(); for( String item: list ) { b.append( replacement ).append( item ); } return b.toString().substring( replacement.length() ); } 

Que parece muito semelhante à pergunta original.

Então, se você não quiser adicionar o flask inteiro ao seu projeto, você pode usar isso.

Eu acho que não há nada errado com o seu código original. Na verdade, a alternativa que todos estão sugerindo parece quase a mesma (embora faça várias validações adicionais)

Aqui está, junto com a licença do Apache 2.0.

 public static String join(Iterator iterator, String separator) { // handle null, zero and one elements before building a buffer if (iterator == null) { return null; } if (!iterator.hasNext()) { return EMPTY; } Object first = iterator.next(); if (!iterator.hasNext()) { return ObjectUtils.toString(first); } // two or more elements StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small if (first != null) { buf.append(first); } while (iterator.hasNext()) { if (separator != null) { buf.append(separator); } Object obj = iterator.next(); if (obj != null) { buf.append(obj); } } return buf.toString(); } 

Agora sabemos, obrigado open source

Java 8 traz o

 Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) 

método, que é nullsafe usando prefix + suffix para valores nulos.

Pode ser usado da seguinte maneira:

 String s = stringList.stream().collect(Collectors.joining(" and ", "prefix_", "_suffix")) 

O método Collectors.joining(CharSequence delimiter) apenas chama Collectors.joining(CharSequence delimiter) joining(delimiter, "", "") internamente.

Com java 1.8 stream pode ser usado,

 import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; List list = Arrays.asList("Bill","Bob","Steve"). String str = list.stream().collect(Collectors.joining(" and ")); 

Você pode usar isso de StringUtils do Spring Framework. Eu sei que já foi mencionado, mas você pode realmente pegar este código e ele funciona imediatamente, sem precisar do Spring para isso.

 // from https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/util/StringUtils.java /* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ public class StringUtils { public static String collectionToDelimitedString(Collection coll, String delim, String prefix, String suffix) { if(coll == null || coll.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); Iterator it = coll.iterator(); while (it.hasNext()) { sb.append(prefix).append(it.next()).append(suffix); if (it.hasNext()) { sb.append(delim); } } return sb.toString(); } } 

Tente isto:

 java.util.Arrays.toString(anArray).replaceAll(", ", ",") .replaceFirst("^\\[","").replaceFirst("\\]$","");