Лучший способ построить строку с разделителями из списка в Java - PullRequest
2 голосов
/ 06 августа 2010

У меня есть список объектов, и у каждого объекта есть строковое свойство. Например, у меня есть List<Person>, а у каждого Person есть свойство firstName. Я хочу создать строку в кавычках, разделенную запятыми, которая выглядит следующим образом:

'James', 'Lily', 'Michael'

Учитывая, что в java, похоже, нет метода соединения (и, кроме того, это немного сложнее, чем простая строка с разделителями), какой самый простой способ сделать это? Я пытался закодировать это немного, но мой код стал очень грязным, и я мог бы использовать некоторые свежие данные.

Ответы [ 9 ]

20 голосов
/ 30 марта 2012

Я использовал это для той же проблемы ( Apache StringUtils )

String joined = "'" + StringUtils.join(arrayOrList,"','") + "'";
3 голосов
/ 06 августа 2010

Если вы хотите сделать это просто и вручную, вы можете сделать что-то вроде этого:

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 голосов
/ 23 июня 2016

Jdk8 Лямбда-решение:

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

Это обеспечивает "," в качестве разделителя и префикс и суффикс ".

2 голосов
/ 06 августа 2010

Просто используйте самый простой способ.Имейте 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 предпочтительнее, чем использование += конкатенации строк, поскольку последняя неявно создает новый экземпляр строки в куче, что может привести к скачкам производительности и памяти примного предметов.

1 голос
/ 07 августа 2010

Вот модульный тест с ожиданиями:

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

И, наконец, Joiner:

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

Используя разныеК конвертерам легко присоединять свойства разных типов.

1 голос
/ 06 августа 2010

Мне нравится

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

, вставляет ненужный оператор if в цикл while.Это означает, что необходимо провести дополнительное сравнение для каждого элемента, когда единственным отличающимся элементом будет последний элемент.

Сдвигая сравнение для проверки, является ли этот элемент последним, для сравнения, если естьболее чем один элемент, нам нужно только переместить добавленный "," в предварительно добавленный "," для каждого элемента, кроме первого

0 голосов
/ 07 августа 2010

Я бы предложил вам сначала добавить метод в ваш 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();
0 голосов
/ 06 августа 2010

Вы можете пройтись по каждому элементу в своем Списке и использовать метод StringBuilder.append (), чтобы добавить каждое Имя в список.Это позволяет использовать строковый класс, который будет создавать новый экземпляр строки каждый раз, когда строка неизменна.

1) инициализировать построитель строк 2) получить количество элементов в списке с помощью List.size ()

int listSize = personList.size()

3) добавьте первое открывающее слово и кавычку к вашей строке

StringBuilderinstance.append("('")

4) используйте цикл for и добавьте каждое имя, заключительную кавычку, запятую и открывающую кавычку вЭкземпляр stringBuilder перед вызовом метода добавления проверяет, равен ли я listSize, если вы находитесь за последним индексом, только добавьте имя, кавычку и закрывающее слово:

for(int i = 0, i<listSize, i++)
{    
    if(i == listSize - 1)
        StringBuilderinstance.append(firstName + "')")
    else    
        StringBuilderinstance.append(firstName + "', '")
}
0 голосов
/ 06 августа 2010

Простое решение, реализованное в ядре Java (без внешних зависимостей), которое не выполняет условную оценку внутри цикла, может выглядеть так:плохо работает на Java.

...