Самый простой способ разделить запятую?

Какой самый простой способ разделить запятую в списке в Java?

Я знаю несколько способов сделать это, но мне интересно, каков наилучший способ (где "лучший" означает самый ясный и/или самый короткий, а не самый эффективный).

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

List --> Item ( , Item ) *
List --> ( Item , ) * Item

Пример решения 1:

boolean isFirst = true;
for (Item i : list) {
  if (isFirst) {
    System.out.print(i);        // no comma
    isFirst = false;
  } else {
    System.out.print(", "+i);   // comma
  }
}

Пример решения 2 - создайте подсписок:

if (list.size()>0) {
  System.out.print(list.get(0));   // no comma
  List theRest = list.subList(1, list.size());
  for (Item i : theRest) {
    System.out.print(", "+i);   // comma
  }
}

Пример решения 3:

  Iterator<Item> i = list.iterator();
  if (i.hasNext()) {
    System.out.print(i.next());
    while (i.hasNext())
      System.out.print(", "+i.next());
  }

Они относятся к первому пункту специально; вместо этого можно было бы относиться к последнему специально.

Кстати, вот как реализован List toString (он унаследован от AbstractCollection) в Java 1.6:

public String toString() {
    Iterator<E> i = iterator();
    if (! i.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = i.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! i.hasNext())
            return sb.append(']').toString();
        sb.append(", ");
    }
}

Он выходит из цикла раньше, чтобы избежать запятой после последнего элемента. Кстати, это первый раз, когда я вспоминаю, что видел "(этот сборник)"; вот код, чтобы спровоцировать это:

List l = new LinkedList();
l.add(l);
System.out.println(l);

Я приветствую любое решение, даже если они используют неожиданные библиотеки (regexp?); а также решения на языках, отличных от Java (например, я думаю, что Python/Ruby имеют вкрапленную функцию - как это реализовано?).

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

Инструментарий EDIT упомянул похожий вопрос: последняя итерация улучшенного цикла for в Java

И еще: заслуживает ли последний элемент цикла отдельного обращения?

Ответ 1

Java 8 и позже

Используя класс StringJoiner:

StringJoiner joiner = new StringJoiner(",");
for (Item item : list) {
    joiner.add(item.toString());
}
return joiner.toString();

Использование Stream и Collectors:

return list.stream().
       map(Object::toString).
       collect(Collectors.joining(",")).toString();

Java 7 и более ранние

Смотрите также # 285523

String delim = "";
for (Item i : list) {
    sb.append(delim).append(i);
    delim = ",";
}

Ответ 2

org.apache.commons.lang3.StringUtils.join(list,",");

Ответ 3

Java 8 предоставляет несколько новых способов сделать это:

  • Метод join в String.
  • joining коллектор для потоков из класса Collectors.
  • Класс StringJoiner.

Пример:

// Util method for strings and other char sequences
List<String> strs = Arrays.asList("1", "2", "3");
String listStr1 = String.join(",", strs);

// For any type using streams and collectors
List<Object> objs = Arrays.asList(1, 2, 3);
String listStr2 = objs.stream()
    .map(Object::toString)
    .collect(joining(",", "[", "]"));

// Using the new StringJoiner class
StringJoiner joiner = new StringJoiner(", ", "[", "]");
joiner.setEmptyValue("<empty>");
for (Integer i : objs) {
  joiner.add(i.toString());
}
String listStr3 = joiner.toString();

Подход с использованием потоков предполагает import static java.util.stream.Collectors.joining; ,

Ответ 4

Joiner.on(",").join(myList)

Joiner.

Ответ 5

Если вы используете Spring Framework, вы можете сделать это с помощью StringUtils:

public static String arrayToDelimitedString(Object[] arr)
public static String arrayToDelimitedString(Object[] arr, String delim)
public static String collectionToCommaDelimitedString(Collection coll)
public static String collectionToCommaDelimitedString(Collection coll, String delim)

Ответ 6

На основе реализации Java List toString:

Iterator i = list.iterator();
for (;;) {
  sb.append(i.next());
  if (! i.hasNext()) break;
  ab.append(", ");
}

Он использует такую ​​грамматику:

List --> (Item , )* Item

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

Ответ 7

String delimiter = ",";
StringBuilder sb = new StringBuilder();
for (Item i : list) {
    sb.append(delimiter).append(i);
}
sb.toString().replaceFirst(delimiter, "");

Ответ 8

Существует довольно хороший способ добиться этого с помощью Java 8:

List<String> list = Arrays.asList(array);
String joinedString = String.join(",", list);

Ответ 9

for(int i=0, length=list.size(); i<length; i++)
  result+=(i==0?"":", ") + list.get(i);

Ответ 10

Один из вариантов для цикла foreach:

StringBuilder sb = new StringBuilder();
for(String s:list){
  if (sb.length()>0) sb.append(",");
  sb.append(s);
}

Ответ 11

StringBuffer result = new StringBuffer();
for(Iterator it=list.iterator; it.hasNext(); ) {
  if (result.length()>0)
    result.append(", ");
  result.append(it.next());
}

Обновление. Как отметил Дэйв Уэбб в комментариях, это может привести к неправильным результатам, если первые элементы в списке - это пустые строки.

Ответ 12

Я обычно делаю это:

StringBuffer sb = new StringBuffer();
Iterator it = myList.iterator();
if (it.hasNext()) { sb.append(it.next().toString()); }
while (it.hasNext()) { sb.append(",").append(it.next().toString()); }

Хотя я думаю, что с этой точки зрения я буду выполнять эту проверку в соответствии с реализацией Java;)

Ответ 13

Если вы можете использовать Groovy (который работает на JVM):

def list = ['a', 'b', 'c', 'd']
println list.join(',')

Ответ 14

(Скопируйте пасту моего собственного ответа из здесь.) Многие из описанных здесь решений немного выше, IMHO, особенно те, которые полагаются на внешние библиотеки, Существует хорошая чистая, ясная идиома для достижения списка, разделенного запятыми, которые я всегда использовал. Он полагается на условный (?) Оператор:

Изменить. Исходное решение правильно, но не оптимально в соответствии с комментариями. Повторяя второй раз:

int[] array = {1, 2, 3};
StringBuilder builder = new StringBuilder();
for (int i = 0 ;  i < array.length; i++)
       builder.append(i == 0 ? "" : ",").append(array[i]);

Там вы идете в 4 строках кода, включая объявление массива и StringBuilder.

2nd Edit: Если вы имеете дело с Iterator:

    List<Integer> list = Arrays.asList(1, 2, 3);
    StringBuilder builder = new StringBuilder();
    for (Iterator it = list.iterator(); it.hasNext();)
        builder.append(it.next()).append(it.hasNext() ? "," : "");

Ответ 15

Обычно я использую нечто похожее на версию 3. Он хорошо работает c/С++/ bash/...: P

Ответ 16

Это очень коротко, очень ясно, но дает мне чувствительность ползучих ужасов. Также немного неудобно адаптироваться к разным разделителям, особенно если String (не char).

for (Item i : list)
  sb.append(',').append(i);
if (sb.charAt(0)==',') sb.deleteCharAt(0);

Вдохновленный: Последняя итерация расширенного цикла в java

Ответ 17

Я не компилировал его... но должен работать (или быть близко к работе).

public static <T> String toString(final List<T> list, 
                                  final String delim)
{
    final StringBuilder builder;

    builder = new StringBuilder();

    for(final T item : list)
    {
        builder.append(item);
        builder.append(delim);
    }

    // kill the last delim
    builder.setLength(builder.length() - delim.length());

    return (builder.toString());
}

Ответ 18

StringBuffer sb = new StringBuffer();

for (int i = 0; i < myList.size(); i++)
{ 
    if (i > 0) 
    {
        sb.append(", ");
    }

    sb.append(myList.get(i)); 
}

Ответ 19

Мне несколько нравится этот подход, который я нашел в блоге некоторое время назад. К сожалению, я не помню имя /URL блога.

Вы можете создать класс утилиты/помощника, который выглядит следующим образом:

private class Delimiter
{
    private final String delimiter;
    private boolean first = true;

    public Delimiter(String delimiter)
    {
        this.delimiter = delimiter;
    }

    @Override
    public String toString()
    {
        if (first) {
            first = false;
            return "";
        }

        return delimiter;
    }
}

Использование вспомогательного класса прост как это:

StringBuilder sb = new StringBuilder();
Delimiter delimiter = new Delimiter(", ");

for (String item : list) {
    sb.append(delimiter);
    sb.append(item);
}

Ответ 20

Мне нравится это решение:

String delim = " - ", string = "";

for (String item : myCollection)
    string += delim + item;

string = string.substring(delim.length());

Я предполагаю, что он также может использовать StringBuilder.

Ответ 21

Поскольку ваш разделитель ",", вы можете использовать любое из следующих действий:

public class StringDelim {

    public static void removeBrackets(String string) {
        System.out.println(string.substring(1, string.length() - 1));
    }

    public static void main(String... args) {
        // Array.toString() example
        String [] arr = {"Hi" , "My", "name", "is", "br3nt"};
        String string = Arrays.toString(arr);
        removeBrackets(string);

        // List#toString() example
        List<String> list = new ArrayList<String>();
        list.add("Hi");
        list.add("My");
        list.add("name");
        list.add("is");
        list.add("br3nt");
        string = list.toString();
        removeBrackets(string);

        // Map#values().toString() example
        Map<String, String> map = new LinkedHashMap<String, String>();
        map.put("1", "Hi");
        map.put("2", "My");
        map.put("3", "name");
        map.put("4", "is");
        map.put("5", "br3nt");
        System.out.println(map.values().toString());
        removeBrackets(string);

        // Enum#toString() example
        EnumSet<Days> set = EnumSet.allOf(Days.class);
        string = set.toString();
        removeBrackets(string);
    }

    public enum Days {
        MON("Monday"),
        TUE("Tuesday"),
        WED("Wednesday"),
        THU("Thursday"),
        FRI("Friday"),
        SAT("Saturday"),
        SUN("Sunday");

        private final String day;

        Days(String day) {this.day = day;}
        public String toString() {return this.day;}
    }
}

Если ваш разделитель НИЧЕГО, иначе это не сработает для вас.

Ответ 22

В Python его легкий

",". join (yourlist)

В С# существует статический метод в классе String

String.Join( ",", yourlistofstrings)

Извините, не уверен в Java, но подумал, что я напишу, как вы спрашивали о других языках. Я уверен, что в Java будет что-то подобное.

Ответ 23

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

Итак, на самом деле вопрос:

"Учитывая цикл и if, как вы думаете, самый ясный способ собрать их вместе?"

Ответ 25

public static String join (List<String> list, String separator) {
  String listToString = "";

  if (list == null || list.isEmpty()) {
   return listToString;
  }

  for (String element : list) {
   listToString += element + separator;
  }

  listToString = listToString.substring(0, separator.length());

  return listToString;
}

Ответ 26

public String toString(List<Item> items)
{
    StringBuilder sb = new StringBuilder("[");

    for (Item item : items)
    {
        sb.append(item).append(", ");
    }

    if (sb.length() >= 2)
    {
        //looks cleaner in C# sb.Length -= 2;
        sb.setLength(sb.length() - 2);
    }

    sb.append("]");

    return sb.toString();
}

Ответ 27

Ни один из ответов не использует рекурсию до сих пор...

public class Main {

    public static String toString(List<String> list, char d) {
        int n = list.size();
        if(n==0) return "";
        return n > 1 ? Main.toString(list.subList(0, n - 1), d) + d
                  + list.get(n - 1) : list.get(0);
    }

    public static void main(String[] args) {
        List<String> list = Arrays.asList(new String[]{"1","2","3"});
        System.out.println(Main.toString(list, ','));
    }

}

Ответ 28

По-моему, это самый простой способ прочитать и понять:

StringBuilder sb = new StringBuilder();
for(String string : strings) {
    sb.append(string).append(',');
}
sb.setLength(sb.length() - 1);
String result = sb.toString();

Ответ 29

private String betweenComma(ArrayList<String> strings) {
    String united = "";
    for (String string : strings) {
        united = united + "," + string;
    }
    return united.replaceFirst(",", "");
}

Ответ 30

Метод

String join(List<Object> collection, String delimiter){
    StringBuilder stringBuilder = new StringBuilder();
    int size = collection.size();
    for (Object value : collection) {
        size --;
        if(size > 0){
            stringBuilder.append(value).append(delimiter);
        }
    }

    return stringBuilder.toString();
}

Использование

Учитывая массив [1,2,3]

join(myArray, ",") // 1,2,3