Лучший способ преобразовать ArrayList в строку

Извините за скучный ответ, но Relevanssi не может заставить работать функцию Jetpack Infinite Scroll. Вам просто нужно отключить его на страницах поиска, как описано в База знаний Relevanssi .

353
задан Hamid Pourjam 18 April 2015 в 22:25
поделиться

8 ответов

В основном использование цикла для итерации по эти ArrayList является единственной опцией:

НЕ используют этот код, продолжают читать в нижнюю часть этого ответа для наблюдения, почему это не желательно, и какой код должен использоваться вместо этого:

ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

String listString = "";

for (String s : list)
{
    listString += s + "\t";
}

System.out.println(listString);

На самом деле, конкатенация строк будет очень хорошо, как javac, компилятор оптимизирует конкатенацию строк как серию append операции на StringBuilder так или иначе. Вот часть дизассемблирования байт-кода от for цикл из вышеупомянутой программы:

   61:  new #13; //class java/lang/StringBuilder
   64:  dup
   65:  invokespecial   #14; //Method java/lang/StringBuilder."<init>":()V
   68:  aload_2
   69:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   72:  aload   4
   74:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   77:  ldc #16; //String \t
   79:  invokevirtual   #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   82:  invokevirtual   #17; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

Как видно, компилятор оптимизирует тот цикл при помощи StringBuilder, таким образом, производительность не должна быть большим беспокойством.

(хорошо, на втором взгляде, эти StringBuilder инстанцируется на каждом повторении цикла, таким образом, это не может быть самый эффективный байт-код. Инстанцирование и использование явного StringBuilder, вероятно, привели бы к лучшей производительности.)

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

Редактирование: , Как указано в комментариях, вышеупомянутая компиляторная оптимизация действительно создает новый экземпляр [1 112] на каждом повторении. (Который я отметил ранее.)

наиболее оптимизированная техника для использования будет ответом [1 120] Paul Tomblin , поскольку это только инстанцирует сингла StringBuilder объект за пределами for цикл.

Перезапись к вышеупомянутому коду к:

ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

StringBuilder sb = new StringBuilder();
for (String s : list)
{
    sb.append(s);
    sb.append("\t");
}

System.out.println(sb.toString());

только инстанцирует StringBuilder однажды за пределами цикла и только выполнит эти два вызова к append метод в цикле, как свидетельствуется в этом байт-коде (который показывает инстанцирование [1 117] и цикл):

   // Instantiation of the StringBuilder outside loop:
   33:  new #8; //class java/lang/StringBuilder
   36:  dup
   37:  invokespecial   #9; //Method java/lang/StringBuilder."<init>":()V
   40:  astore_2

   // [snip a few lines for initializing the loop]
   // Loading the StringBuilder inside the loop, then append:
   66:  aload_2
   67:  aload   4
   69:  invokevirtual   #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   72:  pop
   73:  aload_2
   74:  ldc #15; //String \t
   76:  invokevirtual   #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   79:  pop

Так, действительно ручная оптимизация должна лучше работать как внутренняя часть for, цикл короче и нет никакой потребности инстанцировать StringBuilder на каждом повторении.

316
ответ дан Community 23 November 2019 в 00:23
поделиться

Если Вы не хотите последний \t после последнего элемента, необходимо использовать индекс, чтобы проверить, но помнить, что это только "работает" (т.е. O (n)), когда списки реализуют RandomAccess.

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

StringBuilder sb = new StringBuilder(list.size() * apprAvg); // every apprAvg > 1 is better than none
for (int i = 0; i < list.size(); i++) {
    sb.append(list.get(i));
    if (i < list.size() - 1) {
        sb.append("\t");
    }
}
System.out.println(sb.toString());
3
ответ дан 23 November 2019 в 00:23
поделиться

Изящный способ иметь дело с запаздывающими разделительными символами состоит в том, чтобы использовать Разделитель

StringBuilder buf = new StringBuilder();
Separator sep = new Separator("\t");
for (String each: list) buf.append(sep).append(each);
String s = buf.toString();

Класса, toString метод Разделителя Класса возвращает разделитель, кроме для первого вызова. Таким образом мы печатаем список, не запаздывая (или в этом случае) ведущие разделители.

13
ответ дан akuhn 23 November 2019 в 00:23
поделиться

Большинство проектов Java часто имеет апачское свободное городское население доступный Ленг. StringUtils.join () методы очень хороши и имеют несколько разновидностей для встречи почти каждых потребностей.

public static java.lang.String join(java.util.Collection collection,
                                    char separator)


public static String join(Iterator iterator, String separator) {
    // handle null, zero and one elements before building a buffer 
    Object first = iterator.next();
    if (!iterator.hasNext()) {
        return ObjectUtils.toString(first);
    }
    // two or more elements 
    StringBuffer buf = 
        new StringBuffer(256); // Java default is 16, probably too small 
    if (first != null) {
        buf.append(first);
    }
    while (iterator.hasNext()) {
        if (separator != null) {
            buf.append(separator);
        }
        Object obj = iterator.next();
        if (obj != null) {
            buf.append(obj);
        }
    }
    return buf.toString();
}

Параметры:

набор - Набор значений для объединений, может быть пустой

разделитель - символ разделителя для использования

Возвраты : Строка, к которой присоединяются, пустой указатель, если пустой итератор ввел

С тех пор: 2.3

36
ответ дан Brian 23 November 2019 в 00:23
поделиться

Цикл через него и вызов toString. Нет волшебного пути, и если было, что Вы думаете, что он сделал бы под покрытиями кроме цикличного выполнения через него? О единственной микрооптимизации должен был бы использовать StringBuilder вместо Строки, и даже который не является огромной победой - конкатенирующие строки превращаются в StringBuilder под покрытиями, но по крайней мере если Вы пишете этому тот способ, которым Вы видите то, что продолжается.

StringBuilder out = new StringBuilder();
for (Object o : list)
{
  out.append(o.toString());
  out.append("\t");
}
return out.toString();
38
ответ дан luvieere 23 November 2019 в 00:23
поделиться

Загрузите Apache палата общин Lang и используйте метод

 StringUtils.join(list)

 StringUtils.join(list, ", ") // 2nd param is the separator.

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

я - большой поклонник библиотеки Apache Commons, и я также думаю, что это - большое дополнение к Библиотеке Стандарта Java.

227
ответ дан Ravi Wallau 23 November 2019 в 00:23
поделиться

Это O(n) алгоритм так или иначе (если Вы не сделали некоторое многопоточное решение, где Вы повредили список в несколько подсписков, но я не думаю, именно это Вы просите).

Просто используют StringBuilder как указано ниже:

StringBuilder sb = new StringBuilder();

for (Object obj : list) {
  sb.append(obj.toString());
  sb.append("\t");
}

String finalString = sb.toString();

Эти StringBuilder будет намного быстрее, чем конкатенация строк, потому что Вы не будете повторно инстанцировать String объект на каждой конкатенации.

6
ответ дан Jason Plank 23 November 2019 в 00:23
поделиться

На данный момент это довольно старый разговор, и сообщество apache теперь использует StringBuilder для внутренних целей: http://commons.apache.org/lang/api/src-html/org/apache/commons/lang/ StringUtils.html # line.3045

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

Я основываю это на том, что мы несем некоторые накладные расходы, которых можно было бы избежать, просто перебирая элементы в традиционном цикле for. Вместо этого за кулисами происходят некоторые дополнительные вещи, проверяющие наличие одновременных модификаций, вызовов методов и т. Д. Расширенный цикл for, с другой стороны, приведет к таким же накладным расходам, поскольку итератор используется в объекте Iterable (List).

0
ответ дан 23 November 2019 в 00:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: