从java中的列表构建分隔字符串的最佳方法

时间:2010-08-06 19:16:56

标签: java string join delimiter

我有一个对象列表,每个对象都有一个字符串属性。例如,我有List<Person>,每个Person都有firstName属性。我想构建一个逗号分隔的引用字符串,如下所示:

'James', 'Lily', 'Michael'

考虑到java似乎没有连接方法(此外,这比简单的分隔字符串复杂一点),最简单的方法是什么?我一直试图对此进行编码,但我的代码变得非常混乱,我可以使用一些新的输入。

9 个答案:

答案 0 :(得分:20)

我将此用于同一问题(Apache StringUtils

String joined = "'" + StringUtils.join(arrayOrList,"','") + "'";

答案 1 :(得分:3)

如果你想简单地手动完成,你可以这样做:

String mystr = "";
for(int i = 0; i < personlist.size(); i++) {
  mystr += "\'" + personlist.get(i).firstName + "\'";
  if(i != (personlist.size() - 1)) {
    mystr += ", ";
  }
}

现在mystr包含你的列表。请注意,只有在我们没有对列表中的最后一个元素(使用索引personlist.size() - 1)进行操作时才会添加逗号。

当然,有更多优雅/有效的方法来实现这一目标,但在我看来,这个方法最为清晰。

答案 2 :(得分:2)

只需使用最简单的方法。在StringBuilder上循环List,用引号括住每个项目,将其附加到构建器,如果还有更多内容,请附加逗号。

StringBuilder builder = new StringBuilder();
for (int i = 0; i < persons.size(); i++) {
    builder.append("'").append(persons.get(i)).append("'");
    if (i < persons.size() - 1) {
        builder.append(", ");
    }
}
String string = builder.toString();

或者,您也可以使用Iterator

StringBuilder builder = new StringBuilder();
for (Iterator<Person> iter = persons.iterator(); iter.hasNext();) {
    builder.append("'").append(iter.next()).append("'");
    if (iter.hasNext()) {
        builder.append(", ");
    }
}
String string = builder.toString();

请注意,使用StringBuilder比使用+=字符串连接更受欢迎,因为后者隐式在堆上创建一个新的字符串实例,当你有很多项目时可能会占用性能和内存

答案 3 :(得分:2)

Jdk8 Lambda的解决方案:

String quotedAndDelimited = Arrays.stream(values).collect(Collectors.joining("\",\"","\"","\""));

这提供了“,”作为分隔符,以及“。

的前缀和后缀

答案 4 :(得分:1)

我喜欢

if (list != null) {
  Iterator iter = list.iter();
  if (iter.hasNext()) {
    buffer.append(iter.next());
    while (iter.hasNext()) {
      buffer.append(", ");
      buffer.append(iter.next());
    }
  }
}

这样做的关键优势在于90%的执行时间可能在内部while循环中完成,而这个解决方案只需要一次比较来确定我们是否需要退出内部while循环。

其他解决方案也有效,但解决方案如下:

while (iter.hasNext()) {
  buffer.append(iter.next());
  if (iter.hasNext()) {
    buffer.append(", ");
  }
}

在while循环中嵌入一个不必要的if语句。这意味着当唯一不同的元素是最后一个元素时,必须对每个元素进行额外的比较。

如果有多个元素,通过移动比较来检查元素是否是最后一个元素,我们只需要为第一个元素以外的每个元素移动附加的“,”到前面的“,”

答案 5 :(得分:1)

这是具有期望的单元测试:

import static java.util.Arrays.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;   
import org.junit.Test;


public class JoinerTest {

    private static final Converter<Person, String> PERSON_CONVERTER =
        new Converter<Person, String>() {
            @Override
            public String convert(Person object) {
                return object.getFirstName();
            }
    };

    @Test
    public void shouldPresentFirstNames() {
        // given
        Person person1 = new Person();
        person1.setFirstName("foo");
        Person person2 = new Person();
        person2.setFirstName("bar");
        Joiner<Person> joiner = new Joiner<Person>(", ", "\'");

        // when
        String firstNames = joiner.join(PERSON_CONVERTER,
                        asList(person1, person2));

        // then
        assertThat(firstNames, is("\'foo\', \'bar\'"));
    }

}

Converter只是一个界面:

public interface Converter<F, T> {
    T convert(F object);
}

最后是乔伊纳:

public class Joiner<T> {

    private final String delimiter;

    private final String quote;

    public Joiner(String delimiter, String quote) {
        this.delimiter = delimiter;
        this.quote = quote;
    }

    public String join(Converter<T, String> converter, Iterable<T> objects) {
        StringBuilder builder = new StringBuilder();
        for (T object : objects) {
            String string = converter.convert(object);
            builder.append(quote);
            builder.append(string);
            builder.append(quote);
            builder.append(delimiter);
        }
        if (builder.length() > 0) {
            builder.setLength(builder.length() - delimiter.length());
        }
        return builder.toString();
    }
}

通过使用不同的转换器,可以轻松连接不同类型的属性。

答案 6 :(得分:0)

在核心Java(无外部依赖项)中实现的简单解决方案不会在循环内部进行条件评估,可能如下所示:

private static final char QUOTE = '\'';
private static final String SEPARATOR = ", ";

public static String join(List<Person> people) {
    if (people.isEmpty()) {
        return "";
    }
    final StringBuilder builder = new StringBuilder();
    for (Person person : people) {
        builder.append(QUOTE);
        builder.append(person.getFirstName());
        builder.append(QUOTE);
        builder.append(SEPARATOR);
    }
    builder.setLength(builder.length() - SEPARATOR.length());
    return builder.toString();
}

使用StringBuffer避免了大量的字符串连接,这在Java中表现不佳。

答案 7 :(得分:0)

您可以遍历List中的每个项目,并使用StringBuilder.append()方法将每个Name添加到列表中。这可以使用字符串类,每次字符串是不可变的时,它将创建字符串的新实例。

1)初始化你的字符串生成器 2)使用List.size()

获取列表中的项目数
int listSize = personList.size()

3)将第一个开头paren和quote添加到你的字符串

StringBuilderinstance.append("('")

4)使用for循环并将每个名称,结束引号,逗号和开头引用添加到stringBuilder实例,然后在调用append方法检查以查看我是否等于listSize如果你在最后一个索引处只附加firstname,引用和关闭paren:

for(int i = 0, i<listSize, i++)
{    
    if(i == listSize - 1)
        StringBuilderinstance.append(firstName + "')")
    else    
        StringBuilderinstance.append(firstName + "', '")
}

答案 8 :(得分:0)

我建议你先在Person课程中添加一个方法:

Person {
    //...
    String toListEntry() {
        return "\'" + firstName + "\'";
    }
}

现在你可以使用它:

List<Person> list = //... get the list
StringBuilder buf = new StringBuilder(list.get(0).toListEntry());

for(int i = 1; i < list.size(); i++)
    buf.append(" , " + list.get(i).toListEntry());

String stringList = buf.toString();