在Java中构建一系列分隔项的最佳方法是什么?

Sea*_*ins 305 java string

在Java应用程序中工作时,我最近需要组装一个以逗号分隔的值列表,以传递给另一个Web服务,而无需事先知道有多少元素.我能想出的最好的东西是这样的:

public String appendWithDelimiter( String original, String addition, String delimiter ) {
    if ( original.equals( "" ) ) {
        return addition;
    } else {
        return original + delimiter + addition;
    }
}

String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );
Run Code Online (Sandbox Code Playgroud)

我意识到这不是特别有效,因为在整个地方都会创建字符串,但我的目的是为了清晰而不是优化.

在Ruby中,我可以做这样的事情,感觉更优雅:

parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");
Run Code Online (Sandbox Code Playgroud)

但由于Java缺少连接命令,我无法弄清楚任何等价物.

那么,在Java中执行此操作的最佳方法是什么?

小智 521

前Java 8:

Apache的commons lang是你的朋友 - 它提供了一个非常类似于你在Ruby中引用的连接方法:

StringUtils.join(java.lang.Iterable,char)


Java 8:

Java 8通过StringJoiner和提供开箱即用的加入String.join().下面的代码段显示了如何使用它们:

StringJoiner

StringJoiner joiner = new StringJoiner(",");
joiner.add("01").add("02").add("03");
String joinedString = joiner.toString(); // "01,02,03"
Run Code Online (Sandbox Code Playgroud)

String.join(CharSequence delimiter, CharSequence... elements))

String joinedString = String.join(" - ", "04", "05", "06"); // "04 - 05 - 06"
Run Code Online (Sandbox Code Playgroud)

String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

List<String> strings = new LinkedList<>();
strings.add("Java");strings.add("is");
strings.add("cool");
String message = String.join(" ", strings);
//message returned is: "Java is cool"
Run Code Online (Sandbox Code Playgroud)

  • 在Android上,您也可以使用TextUtils.join(). (107认同)
  • 正是我在寻找的东西:来自org.apache.commons.lang3.StringUtils包的StringUtils.join(java.util.Collection,String),jar文件是commons-lang3-3.0.1.jar (4认同)
  • 这不是最好的方式.即使Collection中的Object为null/empty,它也将始终添加char.它干净整洁但有时它会打印出一个双分隔符字符. (3认同)
  • 我想知道 - 如果Collection中的Object的String表示包含分隔符本身,是否考虑到这一点? (2认同)

小智 52

您可以编写一个适用于java.util.Lists的小型连接样式实用程序方法

public static String join(List<String> list, String delim) {

    StringBuilder sb = new StringBuilder();

    String loopDelim = "";

    for(String s : list) {

        sb.append(loopDelim);
        sb.append(s);            

        loopDelim = delim;
    }

    return sb.toString();
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

    List<String> list = new ArrayList<String>();

    if( condition )        list.add("elementName");
    if( anotherCondition ) list.add("anotherElementName");

    join(list, ",");
Run Code Online (Sandbox Code Playgroud)

  • 例如,如果想要减少外部依赖性,这可能是有用的. (29认同)
  • 如果已经存在至少2个实现(apache和guava),为什么要编写自己的方法? (2认同)
  • 我有点像使用loopDelim而不是条件.这是一种破解,但它从循环中删除了一个条件语句.我仍然更喜欢使用迭代器并在循环之前添加第一个元素,但它确实是一个很好的黑客. (2认同)

Kev*_*vin 47

在Android的情况下,来自commons的StringUtils类不可用,所以为此我使用了

android.text.TextUtils.join(CharSequence delimiter, Iterable tokens)
Run Code Online (Sandbox Code Playgroud)

http://developer.android.com/reference/android/text/TextUtils.html


Ale*_*x K 31

谷歌的番石榴库具有com.google.common.base.Joiner类有助于解决这样的任务.

样品:

"My pets are: " + Joiner.on(", ").join(Arrays.asList("rabbit", "parrot", "dog")); 
// returns "My pets are: rabbit, parrot, dog"

Joiner.on(" AND ").join(Arrays.asList("field1=1" , "field2=2", "field3=3"));
// returns "field1=1 AND field2=2 AND field3=3"

Joiner.on(",").skipNulls().join(Arrays.asList("London", "Moscow", null, "New York", null, "Paris"));
// returns "London,Moscow,New York,Paris"

Joiner.on(", ").useForNull("Team held a draw").join(Arrays.asList("FC Barcelona", "FC Bayern", null, null, "Chelsea FC", "AC Milan"));
// returns "FC Barcelona, FC Bayern, Team held a draw, Team held a draw, Chelsea FC, AC Milan"
Run Code Online (Sandbox Code Playgroud)

这是一篇关于Guava的字符串实用程序文章.


mic*_*cha 25

在Java 8中,您可以使用String.join():

List<String> list = Arrays.asList("foo", "bar", "baz");
String joined = String.join(" and ", list); // "foo and bar and baz"
Run Code Online (Sandbox Code Playgroud)

还要看一下Stream API示例的答案.


Vin*_*vic 20

您可以对它进行概括,但正如您所说,Java中没有连接.

可能会更好.

public static String join(Iterable<? extends CharSequence> s, String delimiter) {
    Iterator<? extends CharSequence> iter = s.iterator();
    if (!iter.hasNext()) return "";
    StringBuilder buffer = new StringBuilder(iter.next());
    while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
    return buffer.toString();
}
Run Code Online (Sandbox Code Playgroud)

  • 您想要使用`StringBuilder`.它们是相同的,除了`StringBuffer`提供不必要的线程安全.有人可以编辑它! (2认同)

Stu*_*son 15

使用基于的方法java.lang.StringBuilder!("一个可变的字符序列.")

就像你提到的那样,所有这些字符串连接都在创建字符串. StringBuilder不会这样做.

为什么StringBuilder而不是StringBuffer?来自StringBuilderjavadoc:

在可能的情况下,建议首先使用此类优先于StringBuffer,因为在大多数实现中它会更快.

  • 是的.此外,StringBuffer是线程安全的,而StringBuilder则不是. (3认同)

gla*_*tor 15

在Java 8中你可以这样做:

list.stream().map(Object::toString)
        .collect(Collectors.joining(delimiter));
Run Code Online (Sandbox Code Playgroud)

如果list有空值,你可以使用:

list.stream().map(String::valueOf)
        .collect(Collectors.joining(delimiter))
Run Code Online (Sandbox Code Playgroud)


Eri*_*and 10

我会使用Google Collections.有一个很好的加入设施.
http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/base/Join.html

但如果我想自己写,

package util;

import java.util.ArrayList;
import java.util.Iterable;
import java.util.Collections;
import java.util.Iterator;

public class Utils {
    // accept a collection of objects, since all objects have toString()
    public static String join(String delimiter, Iterable<? extends Object> objs) {
        if (objs.isEmpty()) {
            return "";
        }
        Iterator<? extends Object> iter = objs.iterator();
        StringBuilder buffer = new StringBuilder();
        buffer.append(iter.next());
        while (iter.hasNext()) {
            buffer.append(delimiter).append(iter.next());
        }
        return buffer.toString();
    }

    // for convenience
    public static String join(String delimiter, Object... objs) {
        ArrayList<Object> list = new ArrayList<Object>();
        Collections.addAll(list, objs);
        return join(delimiter, list);
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为它对象集合更好用,因为现在你不必在加入它们之前将对象转换为字符串.


小智 8

Apache commons StringUtils类有一个join方法.


gst*_*low 5

Java 8

stringCollection.stream().collect(Collectors.joining(", "));
Run Code Online (Sandbox Code Playgroud)


小智 5

Java 8 原生类型

List<Integer> example;
example.add(1);
example.add(2);
example.add(3);
...
example.stream().collect(Collectors.joining(","));
Run Code Online (Sandbox Code Playgroud)

Java 8 自定义对象:

List<Person> person;
...
person.stream().map(Person::getAge).collect(Collectors.joining(","));
Run Code Online (Sandbox Code Playgroud)