Как лучше всего создать строку элементов с разделителями в Java?

Во время работы в приложении Java мне недавно потребовалось собрать список значений, разделенных запятыми, для передачи в другой веб-сервис, не зная заранее, сколько элементов там будет. Лучшее, что я мог придумать, было примерно таким:

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

Я понимаю, что это не особенно эффективно, поскольку строки создаются повсюду, но я хотел большей ясности, чем оптимизации.

Вместо этого в Ruby я могу сделать что-то вроде этого, что кажется гораздо более элегантным:

parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");

Но поскольку в Java отсутствует команда соединения, я не мог придумать ничего эквивалентного.

Итак, как лучше всего сделать это на Java?

StringbBilder - это то, что вам нужно - java.lang.StringBuilder.

Yusubov 16.12.2012 18:30

Для Java 8 посмотрите этот ответ: stackoverflow.com/a/22577623/1115554

micha 22.03.2014 16:31
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
329
2
288 616
36
Перейти к ответу Данный вопрос помечен как решенный

Ответы 36

Используйте подход, основанный на java.lang.StringBuilder! («Изменяемая последовательность символов.»)

Как вы упомянули, все эти конкатенации строк создают строки повсюду. StringBuilder этого не сделает.

Почему StringBuilder вместо StringBuffer? Из документации StringBuilder:

Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.

Ага. Кроме того, StringBuffer является потокобезопасным, а StringBuilder - нет.

Jon Onstott 21.03.2013 21:33

Для этого вы можете использовать тип Java StringBuilder. Также есть StringBuffer, но он содержит дополнительную логику безопасности потоков, которая часто не нужна.

Почему бы не написать свой собственный метод join ()? Это будет принимать в качестве параметров набор строк и строку-разделитель. Внутри метода перебирайте коллекцию и создавайте свой результат в StringBuffer.

Вы можете обобщить это, но в 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();
}

Я согласен с этим ответом, но может ли кто-нибудь отредактировать подпись, чтобы она принимала Collection <String> вместо AbstractCollection <String>? Остальной код должен быть таким же, но я думаю, что AbstractCollection - это деталь реализации, которая здесь не имеет значения.

Outlaw Programmer 15.09.2008 18:19

Еще лучше использовать Iterable<String> и просто использовать тот факт, что вы можете выполнять итерацию по нему. В вашем примере вам не нужно количество элементов в коллекции, так что это еще более общий характер.

Jason Cohen 15.09.2008 22:34

Или, что еще лучше, используйте Iterable <? расширяет Charsequence>, а затем вы можете принимать коллекции StringBuilders и Strings, а также потоки и другие строковые вещи. :)

Jason Cohen 15.09.2008 22:35

Вместо этого вы хотите использовать StringBuilder. Они идентичны, за исключением того, что StringBuffer обеспечивает ненужную безопасность потоков. Может кто-нибудь отредактировать его!

Casebash 11.08.2010 08:43

В этом коде есть несколько ошибок. 1. CharSequence имеет заглавную букву s. 2. s.iterator () возвращает Iterator <? расширяет CharSequence>. 3. Iterable не имеет метода isEmpty(), используйте вместо него метод next().

Casebash 12.08.2010 04:42

В целом неплохое решение. Я предполагаю, что, поскольку есть toString (), его можно реализовать даже для Iterable <?>.

Vlasec 13.01.2015 22:16

Вы можете попробовать что-то вроде этого:

StringBuilder sb = new StringBuilder();
if (condition) { sb.append("elementName").append(","); }
if (anotherCondition) { sb.append("anotherElementName").append(","); }
String parameterString = sb.toString();

Похоже, в конце строки останется паразитная запятая, чего я надеялся избежать. (Конечно, поскольку вы знаете, что это есть, вы можете обрезать его, но это тоже пахнет немного неэлегантно.)

Sean McMains 15.09.2008 18:36

public static String join(String[] strings, char del)
{
    StringBuffer sb = new StringBuffer();
    int len = strings.length;
    boolean appended = false;
    for (int i = 0; i < len; i++)
    {
        if (appended)
        {
            sb.append(del);
        }
        sb.append(""+strings[i]);
        appended = true;
    }
    return sb.toString();
}

Вероятно, вам следует использовать StringBuilder с методом append для построения вашего результата, но в остальном это хорошее решение, которое может предложить Java.

Почему бы вам не сделать в Java то же самое, что и в ruby, а именно создать строку, разделенную разделителем, только после того, как вы добавили все части в массив?

ArrayList<String> parms = new ArrayList<String>();
if (someCondition) parms.add("someString");
if (anotherCondition) parms.add("someOtherString");
// ...
String sep = ""; StringBuffer b = new StringBuffer();
for (String p: parms) {
    b.append(sep);
    b.append(p);
    sep = "yourDelimiter";
}

Вы можете переместить этот цикл for в отдельный вспомогательный метод, а также использовать StringBuilder вместо StringBuffer ...

Редактировать: исправлен порядок добавления.

Да, зачем вам использовать StringBuffer вместо StringBuilder (поскольку вы используете Java 1.5+)? У вас также есть неправильные дополнения.

Tom Hawtin - tackline 15.09.2008 18:22
Ответ принят как подходящий

До Java 8:

Общий язык Apache - ваш друг - он предоставляет метод соединения, очень похожий на тот, на который вы ссылаетесь в 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"

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

String joinedString = String.join(" - ", "04", "05", "06"); // "04 - 05 - 06"

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"

Мне интересно - учитывается ли это, если строковое представление объекта в коллекции содержит сам символ-разделитель?

GreenieMeanie 09.07.2009 00:03

Именно то, что я искал: StringUtils.join (java.util.Collection, String) из пакета org.apache.commons.lang3.StringUtils, файл jar - commons-lang3-3.0.1.jar

Umar 30.08.2011 10:58

На Android вы также можете использовать TextUtils.join ().

James Wald 01.03.2012 03:07

Это не лучший способ. Он всегда будет добавлять символ, даже если объект в коллекции нулевой / пустой. Это красиво и чисто, но иногда он печатает символ с двойным разделителем.

Stephan Schielke 30.08.2012 12:32

Интересно, в чем смысл такого API, если он не может обрабатывать нулевые и пустые значения

arunwithasmile 28.08.2020 13:43

StringUtils.join также работает, например, для Long, а String.join - нет. Таким образом, решение Apache по-прежнему полезно после Java 8

Sadap 08.02.2021 22:21

Вы можете написать небольшой служебный метод в стиле соединения, который работает с 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();
}

Тогда используйте это так:

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

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

    join(list, ",");

зачем писать собственный метод, если уже существует как минимум 2 реализации (apache и guava)?

Timofey 24.11.2012 15:16

Это может быть полезно, например, если кто-то хочет иметь меньше внешних зависимостей.

Thomas Zumbrunn 10.02.2013 01:10

Мне нравится, как используется loopDelim вместо условия. Это своего рода взлом, но он удаляет условный оператор из цикла. Я по-прежнему предпочитаю использовать итератор и добавлять первый элемент перед циклом, но это действительно хороший прием.

Vlasec 13.01.2015 22:13

Не могли бы вы изменить List<String> в своем инициализаторе на Iterator<?> и получить тот же эффект?

k_g 22.02.2015 03:56

@ Тим Например, apache не пропускает пустые строки.

banterCZ 19.05.2015 11:55

Это работает так же хорошо и становится более гибким, если вы измените параметр List <String> на параметр Iterable <String>.

Andrew Sumsion 09.12.2018 06:11

В общем, примерно так:

public static String appendWithDelimiter(String original, String addition, String delimiter) {

if (original.equals("")) {
    return addition;
} else {
    StringBuilder sb = new StringBuilder(original.length() + addition.length() + delimiter.length());
        sb.append(original);
        sb.append(delimiter);
        sb.append(addition);
        return sb.toString();
    }
}

Проблема здесь в том, что он, кажется, вызывает выделение appendWithDelimiter (). Решение должно иметь один и только один StringBuffer и работать с этим единственным экземпляром.

Stu Thompson 15.09.2008 18:22

Класс Apache Commons StringUtils имеет метод соединения.

Не знаю, действительно ли это лучше, но, по крайней мере, он использует StringBuilder, который может быть немного более эффективным.

Ниже приведен более общий подход, если вы можете создать список параметров ПЕРЕД выполнением любого ограничения параметров.

// Answers real question
public String appendWithDelimiters(String delimiter, String original, String addition) {
    StringBuilder sb = new StringBuilder(original);
    if (sb.length()!=0) {
        sb.append(delimiter).append(addition);
    } else {
        sb.append(addition);
    }
    return sb.toString();
}


// A more generic case.
// ... means a list of indeterminate length of Strings.
public String appendWithDelimitersGeneric(String delimiter, String... strings) {
    StringBuilder sb = new StringBuilder();
    for (String string : strings) {
        if (sb.length()!=0) {
            sb.append(delimiter).append(string);
        } else {
            sb.append(string);
        }
    }

    return sb.toString();
}

public void testAppendWithDelimiters() {
    String string = appendWithDelimitersGeneric(",", "string1", "string2", "string3");
}

Ваш подход не так уж плох, но вы должны использовать StringBuffer вместо использования знака +. У символа + есть большой недостаток, заключающийся в том, что новый экземпляр String создается для каждой отдельной операции. Чем длиннее становится ваша струна, тем больше накладные расходы. Таким образом, использование StringBuffer должно быть самым быстрым способом:

public StringBuffer appendWithDelimiter( StringBuffer original, String addition, String delimiter ) {
        if ( original == null ) {
                StringBuffer buffer = new StringBuffer();
                buffer.append(addition);
                return buffer;
        } else {
                buffer.append(delimiter);
                buffer.append(addition);
                return original;
        }
}

После того, как вы закончили создание своей строки, просто вызовите toString () для возвращенного StringBuffer.

Использование StringBuffer здесь просто замедлит работу без уважительной причины. Использование оператора + приведет к внутреннему использованию более быстрого StringBuilder, поэтому он ничего не выиграет, кроме безопасности потоков, в которой он не нуждается, используя вместо этого StringBuffer.

Fredrik 09.07.2009 00:14

Также ... Утверждение «У символа + есть большой недостаток, заключающийся в том, что новый экземпляр String создается для каждой отдельной операции» неверно. Компилятор сгенерирует из них вызовы StringBuilder.append ().

Fredrik 09.07.2009 00:17

Я бы использовал Коллекции Google. Есть хорошая возможность присоединиться. 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);
    }
}

Я думаю, что это лучше работает с коллекцией объектов, поскольку теперь вам не нужно преобразовывать свои объекты в строки перед тем, как присоединиться к ним.

Вместо использования конкатенации строк вы должны использовать StringBuilder, если ваш код не является многопоточным, и StringBuffer, если он есть.

Вы делаете это немного сложнее, чем должно быть. Начнем с конца вашего примера:

String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );

С небольшим изменением использования StringBuilder вместо String это становится:

StringBuilder parameterString = new StringBuilder();
if (condition) parameterString.append("elementName").append(",");
if (anotherCondition) parameterString.append("anotherElementName").append(",");
...

Когда вы закончите (я полагаю, вам нужно проверить еще несколько условий), просто убедитесь, что вы удалили запятую в конце с помощью такой команды:

if (parameterString.length() > 0) 
    parameterString.deleteCharAt(parameterString.length() - 1);

И, наконец, получите нужную строку с помощью

parameterString.toString();

Вы также можете заменить "," во втором вызове, добавив к нему общую строку-разделитель, которая может быть установлена ​​на что угодно. Если у вас есть список вещей, которые, как вы знаете, необходимо добавить (без каких-либо условий), вы можете поместить этот код в метод, который принимает список строк.

//Note: if you have access to Java5+, 
//use StringBuilder in preference to StringBuffer.  
//All that has to be replaced is the class name.  
//StringBuffer will work in Java 1.4, though.

appendWithDelimiter( StringBuffer buffer, String addition, 
    String delimiter ) {
    if ( buffer.length() == 0) {
        buffer.append(addition);
    } else {
        buffer.append(delimiter);
        buffer.append(addition);
    }
}


StringBuffer parameterBuffer = new StringBuffer();
if ( condition ) { 
    appendWithDelimiter(parameterBuffer, "elementName", "," );
}
if ( anotherCondition ) {
    appendWithDelimiter(parameterBuffer, "anotherElementName", "," );
}

//Finally, to return a string representation, call toString() when returning.
return parameterBuffer.toString(); 

С аргументами переменных Java 5, поэтому вам не нужно явно помещать все свои строки в коллекцию или массив:

import junit.framework.Assert;
import org.junit.Test;

public class StringUtil
{
    public static String join(String delim, String... strings)
    {
        StringBuilder builder = new StringBuilder();

        if (strings != null)
        {
            for (String str : strings)
            {
                if (builder.length() > 0)
                {
                    builder.append(delim).append(" ");
                }
                builder.append(str);
            }
        }           
        return builder.toString();
    }
    @Test
    public void joinTest()
    {
        Assert.assertEquals("", StringUtil.join(",", null));
        Assert.assertEquals("", StringUtil.join(",", ""));
        Assert.assertEquals("", StringUtil.join(",", new String[0]));
        Assert.assertEquals("test", StringUtil.join(",", "test"));
        Assert.assertEquals("foo, bar", StringUtil.join(",", "foo", "bar"));
        Assert.assertEquals("foo, bar, x", StringUtil.join(",", "foo", "bar", "x"));
    }
}

Итак, вы можете сделать несколько вещей, чтобы почувствовать, что вы ищете:

1) Расширить класс List - и добавить к нему метод соединения. Метод соединения просто выполняет работу по объединению и добавлению разделителя (который может быть параметром метода соединения)

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

Решение 1, вероятно, сейчас единственно реальное, хотя Java 7 еще не вышла :) Но оно должно работать нормально.

Чтобы использовать оба из них, вы просто добавляете все свои элементы в список или коллекцию как обычно, а затем вызываете новый настраиваемый метод, чтобы «присоединиться» к ним.

Используйте StringBuilder и класс Separator

StringBuilder buf = new StringBuilder();
Separator sep = new Separator(", ");
for (String each : list) {
    buf.append(sep).append(each);
}

Разделитель оборачивает разделитель. Разделитель возвращается методом toString Separator, кроме случаев, когда первый вызов возвращает пустую строку!

Исходный код для класса Separator

public class Separator {

    private boolean skipFirst;
    private final String value;

    public Separator() {
        this(", ");
    }

    public Separator(String value) {
        this.value = value;
        this.skipFirst = true;
    }

    public void reset() {
        skipFirst = true;
    }

    public String toString() {
        String sep = skipFirst ? "" : value;
        skipFirst = false;
        return sep;
    }

}

Как насчет модификации Separator, чтобы он использовал StringBuilder вместо конкатенации Strings?

Mohamed Nuur 03.06.2011 02:14

@Mohamed Separator просто возвращает разделитель, но не объединяет саму строку.

akuhn 09.06.2011 04:41

Что это за класс Separator ??? Почему бы просто не использовать простую строку ..?!

maxxyme 28.12.2016 15:14

использовать Доллар просто, набрав:

String joined = $(aCollection).join(",");

NB: это работает также для массивов и других типов данных.

Выполнение

Внутри он использует очень хитрый трюк:

@Override
public String join(String separator) {
    Separator sep = new Separator(separator);
    StringBuilder sb = new StringBuilder();

    for (T item : iterable) {
        sb.append(sep).append(item);
    }

    return sb.toString();
}

класс Separator возвращает пустую строку только при первом вызове, а затем возвращает разделитель:

class Separator {

    private final String separator;
    private boolean wasCalled;

    public Separator(String separator) {
        this.separator = separator;
        this.wasCalled = false;
    }

    @Override
    public String toString() {
        if (!wasCalled) {
            wasCalled = true;
            return "";
        } else {
            return separator;
        }
    }
}

Что, если я хочу использовать разделитель на каждой строке (записи) файла или что-то в этом роде? каждый раз создавать новый Separator? в тот момент, когда вы ввели атрибут wasCalled, вы добавили проблем с потоками. Наконец, что такое $? Это был вопрос Java.

ring bearer 03.02.2014 10:01

Небольшое улучшение [скорости] версии от izb:

public static String join(String[] strings, char del)
{
    StringBuilder sb = new StringBuilder();
    int len = strings.length;

    if (len > 1) 
    {
       len -= 1;
    }else
    {
       return strings[0];
    }

    for (int i = 0; i < len; i++)
    {
       sb.append(strings[i]).append(del);
    }

    sb.append(strings[i]);

    return sb.toString();
}

В случае Android класс StringUtils из общего пользования недоступен, поэтому для этого я использовал

android.text.TextUtils.join(CharSequence delimiter, Iterable tokens)

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

В Библиотека Google Guava есть класс 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"

Вот статья о струнных утилитах Guava.

Если вы используете Коллекции Eclipse, вы можете использовать makeString() или appendString().

makeString() возвращает представление String, подобное toString().

Имеет три формы

  • makeString(start, separator, end)
  • makeString(separator) по умолчанию начинается и заканчивается пустыми строками
  • makeString() по умолчанию использует разделитель ", " (запятая и пробел)

Пример кода:

MutableList<Integer> list = FastList.newListWith(1, 2, 3);
assertEquals("[1/2/3]", list.makeString("[", "/", "]"));
assertEquals("1/2/3", list.makeString("/"));
assertEquals("1, 2, 3", list.makeString());
assertEquals(list.toString(), list.makeString("[", ", ", "]"));

appendString() похож на makeString(), но присоединяется к Appendable (например, StringBuilder) и является void. Он имеет те же три формы с дополнительным первым аргументом, добавляемым.

MutableList<Integer> list = FastList.newListWith(1, 2, 3);
Appendable appendable = new StringBuilder();
list.appendString(appendable, "[", "/", "]");
assertEquals("[1/2/3]", appendable.toString());

Если вы не можете преобразовать свою коллекцию в тип Eclipse Collections, просто адаптируйте ее с помощью соответствующего адаптера.

List<Object> list = ...;
ListAdapter.adapt(list).makeString(",");

Примечание: Я участник коллекций Eclipse.

В Java 8 вы можете использовать String.join():

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

Также посмотрите этот ответ для примера Stream API.

И минимальный (если вы не хотите включать Apache Commons vs Guava в зависимости проекта только для объединения строк)

/**
 *
 * @param delim : String that should be kept in between the parts
 * @param parts : parts that needs to be joined
 * @return  a String that's formed by joining the parts
 */
private static final String join(String delim, String... parts) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < parts.length - 1; i++) {
        builder.append(parts[i]).append(delim);
    }
    if (parts.length > 0){
        builder.append(parts[parts.length - 1]);
    }
    return builder.toString();
}

Используйте разделитель вместо File.separator.

Pradeep Kumar 01.02.2015 04:53

в Java 8 это можно сделать так:

list.stream().map(Object::toString)
        .collect(Collectors.joining(delimiter));

если в списке есть нули, вы можете использовать:

list.stream().map(String::valueOf)
        .collect(Collectors.joining(delimiter))

он также поддерживает префикс и суффикс:

list.stream().map(String::valueOf)
        .collect(Collectors.joining(delimiter, prefix, suffix));

Для тех, кто находится в контексте Spring, также будет полезен их класс StringUtils:

Есть много полезных ярлыков, например:

  • collectionToCommaDelimitedString (сборник coll)
  • collectionToDelimitedString (Коллекция, разделитель строк)
  • arrayToDelimitedString (Object [] arr, разделитель строк)

и много других.

Это может быть полезно, если вы еще не используете Java 8 и уже находитесь в контексте Spring.

Я предпочитаю это против Apache Commons (хотя тоже очень хорошо) для поддержки Collection, что проще:

// Encoding Set<String> to String delimited 
String asString = org.springframework.util.StringUtils.collectionToDelimitedString(codes, ";");

// Decoding String delimited to Set
Set<String> collection = org.springframework.util.StringUtils.commaDelimitedListToSet(asString);

Исправьте ответ Роба Дикерсона.

Легче использовать:

public static String join(String delimiter, String... values)
{
    StringBuilder stringBuilder = new StringBuilder();

    for (String value : values)
    {
        stringBuilder.append(value);
        stringBuilder.append(delimiter);
    }

    String result = stringBuilder.toString();

    return result.isEmpty() ? result : result.substring(0, result.length() - 1);
}

Java 8

stringCollection.stream().collect(Collectors.joining(", "));

Если вы используете Spring MVC, вы можете попробовать выполнить следующие шаги.

import org.springframework.util.StringUtils;

List<String> groupIds = new List<String>;   
groupIds.add("a");    
groupIds.add("b");    
groupIds.add("c");

String csv = StringUtils.arrayToCommaDelimitedString(groupIds.toArray());

Это приведет к a,b,c

Лично я довольно часто использую следующее простое решение для логирования:

List lst = Arrays.asList("ab", "bc", "cd");
String str = lst.toString().replaceAll("[\[\]]", "");

Собственный тип Java 8

List<Integer> example;
example.add(1);
example.add(2);
example.add(3);
...
example.stream().collect(Collectors.joining(","));

Пользовательский объект Java 8:

List<Person> person;
...
person.stream().map(Person::getAge).collect(Collectors.joining(","));

Если вы хотите применить запятую в Списке свойств объекта. Это способ, который я нашел наиболее полезным.

здесь getName () - строковое свойство класса, к которому я пытался добавить ",".

Строка message = listName.stream (). Map (список -> list.getName ()). Collect (Collectors.joining (","));

Другие вопросы по теме