Java 从集合/数组/列表创建逗号分隔字符串的最复杂方法是什么?

Java 从集合/数组/列表创建逗号分隔字符串的最复杂方法是什么?,java,sql,string,Java,Sql,String,在使用数据库的过程中,我注意到我编写了查询字符串,在这个字符串中,我必须在列表/数组/集合的where子句中设置一些限制。应该是这样的: select * from customer where customer.id in (34, 26, ..., 2); SELECT.... FROM.... WHERE ID IN( ?, ?,....?) 您可以将其简化为这样一个问题,即您拥有字符串集合,并且希望在一个字符串中创建一个以逗号分隔的字符串列表 到目前为止,我使用的方法是: Stri

在使用数据库的过程中,我注意到我编写了查询字符串,在这个字符串中,我必须在列表/数组/集合的where子句中设置一些限制。应该是这样的:

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, ",");