106

在 Java 中用逗号分隔列表的最清晰方法是什么?

我知道几种方法,但我想知道最好的方法是什么(“最好”意味着最清晰和/或最短,而不是最有效的。

我有一个列表,我想遍历它,打印每个值。我想在每个项目之间打印一个逗号,但不是在最后一个之后(也不在第一个之前)。

List --> Item ( , Item ) *
List --> ( Item , ) * Item

示例解决方案 1:

boolean isFirst = true;
for (Item i : list) {
  if (isFirst) {
    System.out.print(i);        // no comma
    isFirst = false;
  } else {
    System.out.print(", "+i);   // comma
  }
}

示例解决方案 2 - 创建子列表:

if (list.size()>0) {
  System.out.print(list.get(0));   // no comma
  List theRest = list.subList(1, list.size());
  for (Item i : theRest) {
    System.out.print(", "+i);   // comma
  }
}

示例解决方案 3:

  Iterator<Item> i = list.iterator();
  if (i.hasNext()) {
    System.out.print(i.next());
    while (i.hasNext())
      System.out.print(", "+i.next());
  }

这些特别对待第一项;可以改为特殊对待最后一个。

顺便说一下,这是List toString Java 1.6 中的实现方式(继承自AbstractCollection):

public String toString() {
    Iterator<E> i = iterator();
    if (! i.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = i.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! i.hasNext())
            return sb.append(']').toString();
        sb.append(", ");
    }
}

它提前退出循环以避免最后一项之后的逗号。顺便说一句:这是我记得第一次看到“(这个集合)”;这是激发它的代码:

List l = new LinkedList();
l.add(l);
System.out.println(l);

我欢迎任何解决方案,即使他们使用了意想不到的库(正则表达式?);以及除 Java 之外的其他语言的解决方案(例如,我认为 Python/Ruby 有一个intersperse函数——它是如何实现的?)。

澄清:我所说的库是指标准的 Java 库。对于其他库,我认为它们与其他语言一起使用,并且有兴趣了解它们是如何实现的。

EDIT工具包提到了一个类似的问题:Java 中增强 for 循环的最后一次迭代

另一个: 循环中的最后一个元素是否值得单独处理?

4

30 回答 30

234

Java 8 及更高版本

使用StringJoiner类和forEach方法:

StringJoiner joiner = new StringJoiner(",");
list.forEach(item -> joiner.add(item.toString());
return joiner.toString();

使用Stream, 和Collectors:

return list.stream().
       map(Object::toString).
       collect(Collectors.joining(",")).toString();

Java 7 及更早版本

另请参阅#285523

String delim = "";
for (Item i : list) {
    sb.append(delim).append(i);
    delim = ",";
}
于 2009-03-21T11:44:02.320 回答
82
org.apache.commons.lang3.StringUtils.join(list,",");
于 2009-03-21T08:31:12.127 回答
34

Java 8 提供了几种新方法来做到这一点:

例子:

// Util method for strings and other char sequences
List<String> strs = Arrays.asList("1", "2", "3");
String listStr1 = String.join(",", strs);

// For any type using streams and collectors
List<Object> objs = Arrays.asList(1, 2, 3);
String listStr2 = objs.stream()
    .map(Object::toString)
    .collect(joining(",", "[", "]"));

// Using the new StringJoiner class
StringJoiner joiner = new StringJoiner(", ", "[", "]");
joiner.setEmptyValue("<empty>");
for (Integer i : objs) {
  joiner.add(i.toString());
}
String listStr3 = joiner.toString();

使用流的方法假设import static java.util.stream.Collectors.joining;.

于 2014-09-02T13:26:32.183 回答
19
Joiner.on(",").join(myList)

细木工

于 2011-08-31T01:11:07.763 回答
7

如果您使用 Spring 框架,则可以使用StringUtils

public static String arrayToDelimitedString(Object[] arr)
public static String arrayToDelimitedString(Object[] arr, String delim)
public static String collectionToCommaDelimitedString(Collection coll)
public static String collectionToCommaDelimitedString(Collection coll, String delim)
于 2009-03-21T16:10:07.860 回答
6

基于 Java 的 List toString 实现:

Iterator i = list.iterator();
for (;;) {
  sb.append(i.next());
  if (! i.hasNext()) break;
  ab.append(", ");
}

它使用这样的语法:

List --> (Item , )* Item

通过基于最后而不是基于第一个,它可以使用相同的测试来检查跳过逗号以检查列表末尾。我认为这个非常优雅,但我不确定清晰度。

于 2009-03-21T11:04:34.803 回答
5

使用 Java 8 有一个很好的方法来实现这一点:

List<String> list = Arrays.asList(array);
String joinedString = String.join(",", list);
于 2016-05-09T13:49:18.600 回答
4
for(int i=0, length=list.size(); i<length; i++)
  result+=(i==0?"":", ") + list.get(i);
于 2009-03-21T08:25:36.620 回答
4
String delimiter = ",";
StringBuilder sb = new StringBuilder();
for (Item i : list) {
    sb.append(delimiter).append(i);
}
sb.toString().replaceFirst(delimiter, "");
于 2013-08-27T16:42:05.740 回答
3

foreach 循环的一种选择是:

StringBuilder sb = new StringBuilder();
for(String s:list){
  if (sb.length()>0) sb.append(",");
  sb.append(s);
}
于 2010-10-26T20:41:11.423 回答
2
StringBuffer result = new StringBuffer();
for(Iterator it=list.iterator; it.hasNext(); ) {
  if (result.length()>0)
    result.append(", ");
  result.append(it.next());
}

更新:正如 Dave Webb 在评论中提到的,如果列表中的第一项是空字符串,这可能不会产生正确的结果。

于 2009-03-21T08:12:48.693 回答
2

我通常这样做:

StringBuffer sb = new StringBuffer();
Iterator it = myList.iterator();
if (it.hasNext()) { sb.append(it.next().toString()); }
while (it.hasNext()) { sb.append(",").append(it.next().toString()); }

虽然我想我会根据 Java 实现从现在开始进行这项检查;)

于 2009-03-21T12:38:00.617 回答
2

如果您可以使用 Groovy(在 JVM 上运行):

def list = ['a', 'b', 'c', 'd']
println list.join(',')
于 2009-03-21T15:53:40.940 回答
2

(从这里复制我自己的答案。)恕我直言,这里描述的许多解决方案都有些过头了,尤其是那些依赖外部库的解决方案。有一个很好的干净、清晰的习惯用法来实现我一直使用的逗号分隔列表。它依赖于条件 (?) 运算符:

编辑:原始解决方案正确,但根据评论不是最佳的。第二次尝试:

int[] array = {1, 2, 3};
StringBuilder builder = new StringBuilder();
for (int i = 0 ;  i < array.length; i++)
       builder.append(i == 0 ? "" : ",").append(array[i]);

就这样,在 4 行代码中,包括数组的声明和 StringBuilder。

第二次编辑:如果您正在处理迭代器:

    List<Integer> list = Arrays.asList(1, 2, 3);
    StringBuilder builder = new StringBuilder();
    for (Iterator it = list.iterator(); it.hasNext();)
        builder.append(it.next()).append(it.hasNext() ? "," : "");
于 2009-03-21T19:32:44.580 回答
1

我通常使用类似于版本 3 的东西。它运行良好 c/c++/bash/...:P

于 2009-03-21T08:16:42.210 回答
1

这很短,很清楚,但给我的感觉带来了令人毛骨悚然的恐惧。适应不同的分隔符也有点尴尬,特别是如果是字符串(不是字符)。

for (Item i : list)
  sb.append(',').append(i);
if (sb.charAt(0)==',') sb.deleteCharAt(0);

灵感来源:Java 中增强 for 循环的最后一次迭代

于 2009-03-21T13:17:55.463 回答
1

我没有编译它......但应该可以工作(或接近工作)。

public static <T> String toString(final List<T> list, 
                                  final String delim)
{
    final StringBuilder builder;

    builder = new StringBuilder();

    for(final T item : list)
    {
        builder.append(item);
        builder.append(delim);
    }

    // kill the last delim
    builder.setLength(builder.length() - delim.length());

    return (builder.toString());
}
于 2009-03-22T05:57:42.503 回答
1
StringBuffer sb = new StringBuffer();

for (int i = 0; i < myList.size(); i++)
{ 
    if (i > 0) 
    {
        sb.append(", ");
    }

    sb.append(myList.get(i)); 
}
于 2009-03-23T00:42:00.443 回答
1

我有点喜欢这种方法,这是我前段时间在博客上发现的。不幸的是,我不记得博客的名称/网址。

您可以创建一个如下所示的实用程序/帮助程序类:

private class Delimiter
{
    private final String delimiter;
    private boolean first = true;

    public Delimiter(String delimiter)
    {
        this.delimiter = delimiter;
    }

    @Override
    public String toString()
    {
        if (first) {
            first = false;
            return "";
        }

        return delimiter;
    }
}

使用辅助类很简单,如下所示:

StringBuilder sb = new StringBuilder();
Delimiter delimiter = new Delimiter(", ");

for (String item : list) {
    sb.append(delimiter);
    sb.append(item);
}
于 2009-03-23T15:18:36.517 回答
1

我喜欢这个解决方案:

String delim = " - ", string = "";

for (String item : myCollection)
    string += delim + item;

string = string.substring(delim.length());

我认为它也可以使用 StringBuilder 。

于 2012-02-10T13:15:35.957 回答
1

因为您的分隔符是“,”,所以您可以使用以下任何一种:

public class StringDelim {

    public static void removeBrackets(String string) {
        System.out.println(string.substring(1, string.length() - 1));
    }

    public static void main(String... args) {
        // Array.toString() example
        String [] arr = {"Hi" , "My", "name", "is", "br3nt"};
        String string = Arrays.toString(arr);
        removeBrackets(string);

        // List#toString() example
        List<String> list = new ArrayList<String>();
        list.add("Hi");
        list.add("My");
        list.add("name");
        list.add("is");
        list.add("br3nt");
        string = list.toString();
        removeBrackets(string);

        // Map#values().toString() example
        Map<String, String> map = new LinkedHashMap<String, String>();
        map.put("1", "Hi");
        map.put("2", "My");
        map.put("3", "name");
        map.put("4", "is");
        map.put("5", "br3nt");
        System.out.println(map.values().toString());
        removeBrackets(string);

        // Enum#toString() example
        EnumSet<Days> set = EnumSet.allOf(Days.class);
        string = set.toString();
        removeBrackets(string);
    }

    public enum Days {
        MON("Monday"),
        TUE("Tuesday"),
        WED("Wednesday"),
        THU("Thursday"),
        FRI("Friday"),
        SAT("Saturday"),
        SUN("Sunday");

        private final String day;

        Days(String day) {this.day = day;}
        public String toString() {return this.day;}
    }
}

如果您的分隔符是其他任何东西,那么这对您不起作用。

于 2012-02-10T13:21:09.197 回答
1

在我看来,这是最容易阅读和理解的:

StringBuilder sb = new StringBuilder();
for(String string : strings) {
    sb.append(string).append(',');
}
sb.setLength(sb.length() - 1);
String result = sb.toString();
于 2013-11-22T19:53:58.420 回答
0

在 Python 中很容易

",".join(你的名单)

在 C# 中,String 类有一个静态方法

String.Join(",", yourlistofstrings)

抱歉,不确定Java,但当您询问其他语言时,我想我会尽力而为。我敢肯定Java中会有类似的东西。

于 2009-03-21T08:11:46.277 回答
0

您也可以无条件地添加分隔符字符串,并在循环结束后删除多余的分隔符。然后开头的“如果列表为空则返回此字符串”将允许您避免最后的检查(因为您无法从空列表中删除字符)

所以问题真的是:

“给定一个循环和一个 if,你认为将它们组合在一起最清晰的方法是什么?”

于 2009-03-21T09:32:42.730 回答
0
if (array.length>0)          // edited in response Joachim's comment
  sb.append(array[i]);
for (int i=1; i<array.length; i++)
  sb.append(",").append(array[i]);

基于逗号分隔列表(Java)的最清晰方式?

使用这个想法: 循环中的最后一个元素是否值得单独处理?

于 2009-03-22T07:31:12.747 回答
0
public static String join (List<String> list, String separator) {
  String listToString = "";

  if (list == null || list.isEmpty()) {
   return listToString;
  }

  for (String element : list) {
   listToString += element + separator;
  }

  listToString = listToString.substring(0, separator.length());

  return listToString;
}
于 2010-09-07T18:53:35.007 回答
0
public String toString(List<Item> items)
{
    StringBuilder sb = new StringBuilder("[");

    for (Item item : items)
    {
        sb.append(item).append(", ");
    }

    if (sb.length() >= 2)
    {
        //looks cleaner in C# sb.Length -= 2;
        sb.setLength(sb.length() - 2);
    }

    sb.append("]");

    return sb.toString();
}
于 2011-11-22T15:39:35.077 回答
0

到目前为止,没有一个答案使用递归......

public class Main {

    public static String toString(List<String> list, char d) {
        int n = list.size();
        if(n==0) return "";
        return n > 1 ? Main.toString(list.subList(0, n - 1), d) + d
                  + list.get(n - 1) : list.get(0);
    }

    public static void main(String[] args) {
        List<String> list = Arrays.asList(new String[]{"1","2","3"});
        System.out.println(Main.toString(list, ','));
    }

}
于 2013-03-12T20:36:49.893 回答
0
private String betweenComma(ArrayList<String> strings) {
    String united = "";
    for (String string : strings) {
        united = united + "," + string;
    }
    return united.replaceFirst(",", "");
}
于 2017-10-28T14:02:32.553 回答
-1

方法

String join(List<Object> collection, String delimiter){
    StringBuilder stringBuilder = new StringBuilder();
    int size = collection.size();
    for (Object value : collection) {
        size --;
        if(size > 0){
            stringBuilder.append(value).append(delimiter);
        }
    }

    return stringBuilder.toString();
}

用法

给定数组 [1,2,3]

join(myArray, ",") // 1,2,3
于 2016-09-29T05:47:10.847 回答