Java 从集合/数组/列表创建逗号分隔字符串的最复杂方法是什么?
在使用数据库的过程中,我注意到我编写了查询字符串,在这个字符串中,我必须在列表/数组/集合的where子句中设置一些限制。应该是这样的:Java 从集合/数组/列表创建逗号分隔字符串的最复杂方法是什么?,java,sql,string,Java,Sql,String,在使用数据库的过程中,我注意到我编写了查询字符串,在这个字符串中,我必须在列表/数组/集合的where子句中设置一些限制。应该是这样的: select * from customer where customer.id in (34, 26, ..., 2); SELECT.... FROM.... WHERE ID IN( ?, ?,....?) 您可以将其简化为这样一个问题,即您拥有字符串集合,并且希望在一个字符串中创建一个以逗号分隔的字符串列表 到目前为止,我使用的方法是: Stri
select * from customer
where customer.id in (34, 26, ..., 2);
SELECT.... FROM.... WHERE ID IN( ?, ?,....?)
您可以将其简化为这样一个问题,即您拥有字符串集合,并且希望在一个字符串中创建一个以逗号分隔的字符串列表
到目前为止,我使用的方法是:
String result = "";
boolean first = true;
for(String string : collectionOfStrings) {
if(first) {
result+=string;
first=false;
} else {
result+=","+string;
}
}
但你可以看到这是非常丑陋的。您无法在第一次查看时看到那里发生了什么,特别是当构造的字符串(如每个SQL查询)变得复杂时
你(更)优雅的方式是什么?我不确定这有多“复杂”,但肯定有点短。它将用于各种不同类型的集合,例如集合、列表等
公共静态最终字符串toSqlList(集合值){
String collectionString=values.toString();
//将Collection.toString()生成的方括号转换为SQL使用的圆括号
返回“(“+collectionString.substring(1,collectionString.length()-1)+”);
}
读者练习:修改此方法,使其正确处理空/空集合:)有一些第三方Java库提供字符串联接方法,但您可能不希望仅为了这样简单的目的而开始使用库。我只想创建一个像这样的助手方法,我认为它比您的版本好一点,它使用StringBuffer,如果您需要连接许多字符串,它将更有效,并且可以处理任何类型的集合
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();
}
公共静态字符串联接(集合值)
{
StringBuffer ret=新的StringBuffer();
对于(T值:值)
{
如果(ret.length()>0)ret.append(“,”);
ret.append(值);
}
返回ret.toString();
}
使用Collection.toString()的另一个建议更短,但这取决于Collection.toString()以非常特定的格式返回字符串,这是我个人不想依赖的。注意:这在11年前编写时是很好的答案,但现在有更好的选项可以在一行中更干净地执行此操作,两者都只使用Java内置类或使用实用程序库。请参阅下面的其他答案
由于字符串是不可变的,如果要在代码中更改字符串,可能需要使用StringBuilder类 StringBuilder类可以看作是一个可变的字符串对象,当其内容被更改时,它会分配更多的内存 通过处理多余的尾随逗号,问题中的原始建议可以写得更清楚、更有效:
我认为像您这样构造连接where子句值的sql不是一个好主意:
SELECT.... FROM.... WHERE ID IN( value1, value2,....valueN)
其中valueX
来自字符串列表
首先,如果您要比较字符串,那么它们必须被引用,如果字符串中可以有引号,这并不简单
其次,如果值来自用户或其他系统,则可能发生SQL注入攻击
这要详细得多,但您应该创建如下字符串:
select * from customer
where customer.id in (34, 26, ..., 2);
SELECT.... FROM.... WHERE ID IN( ?, ?,....?)
然后用
Statement.setString(nParameter,parameterValue)
绑定变量。我今天刚看了做这件事的代码。这是AviewAnew答案的一个变体
collectionOfStrings = /* source string collection */;
String csList = StringUtils.join(collectionOfStrings.toArray(), ",");
我写循环的方式是:
StringBuilder buff = new StringBuilder();
String sep = "";
for (String str : strs) {
buff.append(sep);
buff.append(str);
sep = ",";
}
return buff.toString();
不要担心sep的性能。赋值是非常快的。Hotspot总是倾向于剥离循环的第一次迭代(因为它经常要处理诸如null和单/双晶片内联检查之类的异常情况)
如果你经常使用它(不止一次),把它放在一个共享的方法中
stackoverflow还有一个问题,就是如何将ID列表插入SQL语句。使用的方法:
这只是解决这个问题的另一种方法。虽然不是最简单的方法,但它是有效的,可以完成任务
/**
* 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();
}
/**
*从给定集合创建以逗号分隔的值列表。
*
*@param值类型。
*@param值值集合。
*@返回逗号分隔的值字符串。
*/
公共字符串TopParameterList(集合值){
if(values==null | | values.isEmpty()){
返回“”;//取决于您希望如何处理此案例。。。
}
StringBuilder结果=新建StringBuilder();
迭代器i=值。迭代器();
result.append(i.next().toString());
while(i.hasNext()){
result.append(“,”).append(i.next().toString());
}
返回result.toString();
}
我发现迭代器习惯用法很优雅,因为它有一个对更多元素的测试(为简洁起见,使用ommited null/empty测试):
公共静态字符串转换(列表){
字符串res=“”;
for(Iterator Iterator=list.Iterator();Iterator.hasNext();){
res+=iterator.next()+(iterator.hasNext()?,:);
}
返回res;
}
您可以使用LINQ(到SQL),也可以使用MS的动态查询LINQ示例。您可以尝试
List collections = Arrays.asList(34, 26, "...", 2);
String asString = collection.toString();
// justValues = "34, 26, ..., 2"
String justValues = asString.substring(1, asString.length()-1);
让代码难看的是对第一种情况的特殊处理。这个小片段中的大多数行都用于处理特殊情况,而不是处理代码的常规工作。这就是gimel的解决方案,将特殊处理移到循环之外。有一种特殊情况(好吧,你可以将开始和结束都视为特殊情况,但其中只有一个需要特殊处理),因此在循环中处理它是不必要的复杂。有很多手动解决方案,但我想重申并更新上面Julie的答案。使用 它处理var参数、iterables和数组,并正确处理多个字符的分隔符(与gimmel的答案不同)。它还将处理null va
public static String convert(List<String> list) {
String res = "";
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
res += iterator.next() + (iterator.hasNext() ? "," : "");
}
return res;
}
List collections = Arrays.asList(34, 26, "...", 2);
String asString = collection.toString();
// justValues = "34, 26, ..., 2"
String justValues = asString.substring(1, asString.length()-1);
Joiner.on(", ").join(34, 26, ..., 2)
String s= java.util.Arrays.toString(collectionOfStrings.toArray());
s = s.substing(1, s.length()-1);// [] are guaranteed to be there
@Test
public void join() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
String string = $(list).join(",");
}
StringBuffer inString = new StringBuffer(listOfIDs.get(0).toString());
for (Long currentID : listOfIDs) {
inString.append(",").append(currentID);
}
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);
}
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)
StringUtils.arrayToCommaDelimitedString(
collectionOfStrings.toArray()
)
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();
}
String res = "";
for (String i : values) {
res += res.isEmpty() ? i : ","+i;
}
Arrays.asList(parameters).toString()
String commaSeparatedNames = namesList.toString().replaceAll( "[\\[|\\]| ]", "" ); // replace [ or ] or blank
for (int i =0; i < tokens.size(); i++){
builder.append(tokens.get(i));
if(i != tokens.size()-1){
builder.append(TOKEN_DELIMITER);
}
}
String.join(", ", collectionOfStrings)
Joiner.on(",").join(collectionOfStrings);
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();
}
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, ","));
}
}
TextUtils.join(",",collectionOfStrings.toArray());
List<String> collectionOfStrings = // List of string to concat
String csvStrings = StringUtils.collectionToDelimitedString(collectionOfStrings, ",");