У меня есть ArrayList который я хочу вывести полностью в виде строки. По сути, я хочу выводить его по порядку, используя toString каждого элемента, разделенного табуляциями. Есть ли какой-нибудь быстрый способ сделать это? Вы могли бы выполнить цикл (или удалить каждый элемент) и объединить его в строку, но я думаю, что это будет очень медленно.
Переведено автоматически
Ответ 1
В Java 8 или более поздней версии:
StringlistString= String.join(", ", list);
В случае, если list не имеет типа String, можно использовать объединяющий коллектор:
До появления Java 8 единственным вариантом было использование цикла для перебора ArrayList:
НЕ используйте этот код, продолжайте читать до конца этого ответа, чтобы понять, почему это нежелательно и какой код следует использовать вместо него:
ArrayList<String> list = newArrayList<String>(); list.add("one"); list.add("two"); list.add("three");
StringlistString="";
for (String s : list) { listString += s + "\t"; }
System.out.println(listString);
На самом деле, конкатенация строк будет просто отличной, поскольку javac компилятор в любом случае оптимизирует конкатенацию строк как серию append операций над StringBuilder. Вот часть дизассемблирования байт-кода из for цикла из вышеупомянутой программы:
Как можно видеть, компилятор оптимизирует этот цикл с помощью StringBuilder, поэтому производительность не должна вызывать большой озабоченности.
(Хорошо, на второй взгляд, StringBuilder создается экземпляр на каждой итерации цикла, поэтому это может быть не самый эффективный байт-код. Создание экземпляра и использование явного StringBuilder, вероятно, повысило бы производительность.)
На самом деле, я думаю, что вывод любого типа (будь то на диск или на экран) будет как минимум на порядок медленнее, чем беспокоиться о производительности конкатенаций строк.
Редактировать: Как указано в комментариях, приведенная выше оптимизация компилятора действительно создает новый экземпляр StringBuilder на каждой итерации. (Что я отмечал ранее.)
Наиболее оптимизированным методом для использования будет ответ Пола Томблина, поскольку он создает экземпляр только одного StringBuilder объекта вне for цикла.
Переписываем приведенный выше код, чтобы:
ArrayList<String> list = newArrayList<String>(); list.add("one"); list.add("two"); list.add("three");
StringBuildersb=newStringBuilder(); for (String s : list) { sb.append(s); sb.append("\t"); }
System.out.println(sb.toString());
Будет создан экземпляр StringBuilder только один раз вне цикла и только два вызова append метода внутри цикла, как показано в этом байт-коде (который показывает создание экземпляра StringBuilder и цикла):
// 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 на каждой итерации.
Ответ 4
Загрузите язык Apache Commons Lang и используйте метод
StringUtils.join(list)
StringUtils.join(list, ", ") // 2nd param is the separator.
Вы, конечно, можете реализовать это самостоятельно, но их код полностью протестирован и, вероятно, является наилучшей возможной реализацией.
Я большой поклонник библиотеки Apache Commons, и я также считаю, что это отличное дополнение к стандартной библиотеке Java.