3

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

'James', 'Lily', 'Michael'

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

4

9 回答 9

21

我用它来解决同样的问题(Apache StringUtils

String joined = "'" + StringUtils.join(arrayOrList,"','") + "'";
于 2012-03-30T18:55:57.237 回答
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)。

当然,还有更优雅/更有效的方法来实现这一点,但在我看来,这是最清晰的。

于 2010-08-06T19:35:30.697 回答
2

只需使用最直接的方式。在StringBuilder, 上循环List,用引号括住每个项目,将其附加到 builder 中,如果还有更多内容,请附加逗号。

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();

请注意,使用 aStringBuilder优于使用+=字符串连接,因为后者隐式在堆上创建一个新的字符串实例,当您有很多项目时,这可能会占用性能和内存。

于 2010-08-06T19:37:21.750 回答
2

Jdk8 Lambda的解决方案:

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

这提供了“,”作为分隔符,以及“”的前缀和后缀。

于 2016-06-23T13:18:46.623 回答
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 语句。这意味着当唯一不同的元素是最后一个元素时,必须对每个元素进行额外的比较。

通过将检查元素是否是最后一个元素的比较转移到如果有多个元素的比较,我们只需将附加的“,”移动到前面的“,”对于除第一个元素之外的每个元素

于 2010-08-06T19:52:05.373 回答
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\'"));
    }

}

转换器只是一个接口:

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();
    }
}

通过使用不同的转换器,可以很容易地连接不同类型的属性。

于 2010-08-06T22:39:44.070 回答
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 中表现不佳。

于 2010-08-06T19:38:55.637 回答
0

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

1) 初始化您的字符串生成器 2) 使用 List.size() 获取列表中的项目数

int listSize = personList.size()

3)将第一个左括号和引号添加到您的字符串

StringBuilderinstance.append("('")

4) 使用 for 循环并将每个名称、结束引号、逗号和开始引号添加到 stringBuilder 实例,在调用 append 方法之前检查 i 是否等于 listSize 如果你在最后一个索引只附加名字、引号和结束父母:

for(int i = 0, i<listSize, i++)
{    
    if(i == listSize - 1)
        StringBuilderinstance.append(firstName + "')")
    else    
        StringBuilderinstance.append(firstName + "', '")
}
于 2010-08-06T19:39:58.327 回答
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();
于 2010-08-06T20:24:39.873 回答