varios tokens son separar por los leer ejercicios ejemplo delimitadores delimitado cuales con comas array archivo java sql string

java - tokens - ¿La forma más sofisticada para crear cadenas separadas por comas de una colección/matriz/lista?



split con varios delimitadores java (30)

Durante mi trabajo con las bases de datos noté que escribo cadenas de consulta y en esta cadena tengo que poner varias restricciones en la cláusula where de una lista / matriz / colección. Debería verse así:

select * from customer where customer.id in (34, 26, ..., 2);

Puede simplificar esto reduciendo esto a la pregunta de que tiene una colección de cadenas y desea crear una lista separada por comas de estas cadenas en una sola cadena.

Mi enfoque que he usado hasta ahora es algo así:

String result = ""; boolean first = true; for(String string : collectionOfStrings) { if(first) { result+=string; first=false; } else { result+=","+string; } }

Pero esto es lo que puedes ver muy feo. No se puede ver lo que sucede allí a primera vista, especialmente cuando las cadenas construidas (como todas las consultas SQL) se complican.

¿Cuál es tu forma (más) elegante?


Acabo de registrar una prueba para mi dollar biblioteca:

@Test public void join() { List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); String string = $(list).join(","); }

crea una envoltura fluida alrededor de lists / arrays / strings / etc usando solo una importación estática : $ .

NB :

utilizando rangos, la lista anterior se puede volver a escribir como $(1, 5).join(",")


Acabo de ver el código que hizo esto hoy. Esta es una variación de la respuesta de AviewAnew.

collectionOfStrings = /* source string collection */; String csList = StringUtils.join(collectionOfStrings.toArray(), ",");

El StringUtils (<- commons.lang 2.x, o commons.lang 3.x link ) que usamos es de Apache Commons .


Aquí hay una versión increíblemente genérica que he creado a partir de una combinación de las sugerencias anteriores:

public static <T> String buildCommaSeparatedString(Collection<T> values) { if (values==null || values.isEmpty()) return ""; StringBuilder result = new StringBuilder(); for (T val : values) { result.append(val); result.append(","); } return result.substring(0, result.length() - 1); }


Aunque creo que tu mejor opción es usar Joiner de Guava, si tuviera que codificarlo a mano, encontraría este enfoque más elegante que la ''primera'' bandera o cortando la última coma.

private String commas(Iterable<String> strings) { StringBuilder buffer = new StringBuilder(); Iterator<String> it = strings.iterator(); if (it.hasNext()) { buffer.append(it.next()); while (it.hasNext()) { buffer.append('',''); buffer.append(it.next()); } } return buffer.toString(); }


Creo que no es una buena idea construir el sql concatenando los valores de la cláusula where como lo está haciendo:

SELECT .... FROM .... WHERE ID IN (valor1, valor2, .... valorN)

Donde valueX proviene de una lista de cadenas.

Primero, si estás comparando cadenas, deben citarse, y esto no es trivial si las cadenas pudieran tener una cita dentro.

En segundo lugar, si los valores provienen del usuario u otro sistema, entonces es posible un ataque de inyección SQL.

Es mucho más detallado, pero lo que debes hacer es crear una cadena como esta:

SELECT .... FROM .... WHERE ID IN (?,?, ....?)

y luego vincula las variables con Statement.setString (nParameter, parameterValue)


Dado que las cadenas son inmutables, es posible que desee utilizar la clase StringBuilder si va a alterar la cadena en el código.

La clase StringBuilder se puede ver como un objeto String mutable que asigna más memoria cuando se altera su contenido.

La sugerencia original en la pregunta se puede escribir de forma aún más clara y eficiente, cuidando la coma final redundante :

StringBuilder result = new StringBuilder(); for(String string : collectionOfStrings) { result.append(string); result.append(","); } return result.length() > 0 ? result.substring(0, result.length() - 1): "";



En Android deberías usar esto:

TextUtils.join(",",collectionOfStrings.toArray());


En caso de que alguien haya tropezado con esto en tiempos más recientes, he agregado una variación simple usando Java 8 reduce() . También incluye algunas de las soluciones ya mencionadas por otros:

import java.util.Arrays; import java.util.List; import org.apache.commons.lang.StringUtils; import com.google.common.base.Joiner; public class Dummy { public static void main(String[] args) { List<String> strings = Arrays.asList("abc", "de", "fg"); String commaSeparated = strings .stream() .reduce((s1, s2) -> {return s1 + "," + s2; }) .get(); System.out.println(commaSeparated); System.out.println(Joiner.on('','').join(strings)); System.out.println(StringUtils.join(strings, ",")); } }


Encontré la expresión idiomática de iterador elegante, porque tiene una prueba para más elementos (prueba omitida nula / vacía para abreviar):

public static String convert(List<String> list) { String res = ""; for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) { res += iterator.next() + (iterator.hasNext() ? "," : ""); } return res; }


Esta será la solución más corta hasta ahora, excepto el uso de Guava o Apache Commons.

String res = ""; for (String i : values) { res += res.isEmpty() ? i : ","+i; }

Bueno con 0,1 y n lista de elementos. Pero deberás verificar la lista nula. Yo uso esto en GWT, así que estoy bien sin StringBuilder allí. Y para listas cortas con solo dos elementos, está bien también en otro lugar;)


Existen algunas bibliotecas de Java de terceros que proporcionan el método de unión de cadenas, pero es probable que no desee comenzar a usar una biblioteca solo por algo simple como eso. Simplemente crearía un método de ayuda como este, que creo que es un poco mejor que su versión. Utiliza StringBuffer, que será más eficiente si necesita unir muchas cadenas, y funciona en una colección de cualquier tipo.

public static <T> String join(Collection<T> values) { StringBuffer ret = new StringBuffer(); for (T value : values) { if (ret.length() > 0) ret.append(","); ret.append(value); } return ret.toString(); }

Otra sugerencia con el uso de Collection.toString () es más corta, pero eso depende de que Collection.toString () devuelva una cadena en un formato muy específico, en lo que personalmente no quisiera confiar.


Hay muchas soluciones manuales para esto, pero quería reiterar y actualizar la respuesta de Julie anterior. Utiliza google-collections.googlecode.com/svn/trunk/javadoc/com/google/… .

Joiner.on(", ").join(34, 26, ..., 2)

Maneja var args, iterables y arrays y maneja correctamente los separadores de más de un char (a diferencia de la respuesta de gimmel). También manejará valores nulos en su lista si lo necesita.


Hay una manera fácil. Puedes obtener tu resultado en una sola línea.

String memberIdsModifiedForQuery = memberIds.toString().replace("[", "(").replace("]", ")");

Para obtener una idea completa, verifique el código a continuación

public static void main(String[] args) { List<Integer>memberIds=new ArrayList<Integer>(); //This contain member ids we want to process //adding some sample values for example memberIds.add(3); memberIds.add(4); memberIds.add(2); String memberIdsModifiedForQuery = memberIds.toString().replace("[", "(").replace("]", ")"); //here you will get (3,4,5) That you can directly use in query System.out.println(memberIdsModifiedForQuery); String exampleQuery="select * from customer where customer.id in "+memberIdsModifiedForQuery+" "; }


La forma en que escribo ese ciclo es:

StringBuilder buff = new StringBuilder(); String sep = ""; for (String str : strs) { buff.append(sep); buff.append(str); sep = ","; } return buff.toString();

No te preocupes por el rendimiento de sep. Una tarea es muy rápida. Hotspot tiende a desprenderse de la primera iteración de un bucle de todos modos (ya que a menudo tiene que ocuparse de rarezas como null y mono / bimorphic enlining cheques).

Si lo usa mucho (más de una vez), colóquelo en un método compartido.

Hay otra pregunta sobre que trata de cómo insertar una lista de identificadores en una declaración SQL.


List token = new ArrayList (resultado); final StringBuilder builder = new StringBuilder ();

for (int i =0; i < tokens.size(); i++){ builder.append(tokens.get(i)); if(i != tokens.size()-1){ builder.append(TOKEN_DELIMITER); } }

builder.toString ();


Lo bueno de la expresión IN es que si tienes valores repetidos, no cambia el resultado. Entonces, simplemente duplique el primer elemento y procese toda la lista. Esto supone que hay al menos un elemento en la lista. Si no hay elementos, sugeriría que primero lo compruebe y luego no ejecute el SQL en absoluto.

Esto hará el truco, es obvio en lo que está haciendo y no depende de ninguna biblioteca externa:

StringBuffer inString = new StringBuffer(listOfIDs.get(0).toString()); for (Long currentID : listOfIDs) { inString.append(",").append(currentID); }


Lo que hace que el código sea feo es el manejo especial para el primer caso. La mayoría de las líneas en este pequeño fragmento están dedicadas, no a hacer el trabajo de rutina del código, sino a manejar ese caso especial. Y eso es lo que las alternativas como Gimel resuelven moviendo el manejo especial fuera del ciclo. Hay un caso especial (bueno, podría ver el inicio y el final como casos especiales, pero solo uno de ellos debe tratarse especialmente), por lo que su manejo dentro del ciclo es innecesariamente complicado.


Los ''métodos'' de join están disponibles en Arrays y en las clases que extienden AbstractCollections pero no anulan el método toString () (como virtualmente todas las colecciones en java.util)

por ejemplo: String s = java.util.Arrays.toString (collectionOfStrings.toArray ());

s = s.substing (1, s.length () - 1); // [] están garantizados para estar allí

esa es una manera bastante extraña, ya que funciona solo para los números por igual.


No estoy seguro de cuán "sofisticado" es esto, pero ciertamente es un poco más corto. Funcionará con diferentes tipos de colecciones, por ejemplo, Set <Integer>, List <String>, etc.

public static final String toSqlList(Collection<?> values) { String collectionString = values.toString(); // Convert the square brackets produced by Collection.toString() to round brackets used by SQL return "(" + collectionString.substring(1, collectionString.length() - 1) + ")"; }

Ejercicio para el lector : modifique este método para que maneje correctamente una colección nula / vacía :)


Otra opción, basada en lo que veo aquí (con ligeras modificaciones).

public static String toString(int[] numbers) { StringBuilder res = new StringBuilder(); for (int number : numbers) { if (res.length() != 0) { res.append('',''); } res.append(number); } return res.toString(); }



Si usa Spring, puede hacer:

StringUtils.arrayToCommaDelimitedString( collectionOfStrings.toArray() )

(paquete org.springframework.util)


Solo otro método para lidiar con este problema. No es el más corto, pero es eficiente y hace el trabajo.

/** * Creates a comma-separated list of values from given collection. * * @param <T> Value type. * @param values Value collection. * @return Comma-separated String of values. */ public <T> String toParameterList(Collection<T> values) { if (values == null || values.isEmpty()) { return ""; // Depending on how you want to deal with this case... } StringBuilder result = new StringBuilder(); Iterator<T> i = values.iterator(); result.append(i.next().toString()); while (i.hasNext()) { result.append(",").append(i.next().toString()); } return result.toString(); }


Tu podrías intentar

List collections = Arrays.asList(34, 26, "...", 2); String asString = collection.toString(); // justValues = "34, 26, ..., 2" String justValues = asString.substring(1, asString.length()-1);



si tiene una matriz puede hacer:

Arrays.asList(parameters).toString()


String commaSeparatedNames = namesList.toString().replaceAll( "[//[|//]| ]", "" ); // replace [ or ] or blank

La representación de cadena consiste en una lista de los elementos de la colección en el orden en que el iterador los devuelve, entre corchetes ("[]"). Los elementos adyacentes están separados por los caracteres "," (coma y espacio).

AbstractCollection javadoc


String.join(", ", collectionOfStrings)

disponible en la api Java8.

alternativa a (sin la necesidad de agregar una dependencia de google guava):

Joiner.on(",").join(collectionOfStrings);


java.util.List<String> lista = new java.util.ArrayList<String>(); lista.add("Hola"); lista.add("Julio"); System.out.println(lista.toString().replace(''['',''('').replace('']'','')'')); $~(Hola, Julio)