Я знаю, что это вопрос новичка, но есть ли эквиваленты строковым операциям C# в Java?
Конкретно я говорю о String.Format и String.Join.
Для join () мне нравится этот ответ: stackoverflow.com/a/6116469/562139





String.format. Что касается присоединения, вам нужно написать свой собственный:
static String join(Collection<?> s, String delimiter) {
StringBuilder builder = new StringBuilder();
Iterator<?> iter = s.iterator();
while (iter.hasNext()) {
builder.append(iter.next());
if (!iter.hasNext()) {
break;
}
builder.append(delimiter);
}
return builder.toString();
}
Вышеизложенное взято из http://snippets.dzone.com/posts/show/91
Точнее: StringBuffer для jdk1.4 и ниже, StringBuilder для jdk1.5 и более поздних версий, поскольку последний не синхронизируется, следовательно, немного быстрее.
Вместо двух вызовов iter.hasNext () я обычно добавляю разделитель, а затем «возвращаю buf.substring (0, buf.length () - delimited.length ())».
Вы можете немного упростить его, выйдя раньше, чтобы избежать разделителя: while (true) (add_iter; if (! Iter.hasNext ()) break; add_delim;}
Объект Java String имеет метод format (начиная с версии 1.5), но не имеет метода join.
Чтобы получить кучу полезных служебных методов String, которые еще не включены, вы можете использовать org.apache.commons.lang.StringUtils.
Коллекции google: google-collections.googlecode.com также имеет Joiner.
К вашему сведению, к комментарию Рона, google-коллекции были переименованы в Guava некоторое время назад.
Вы должны обновить этот ответ, чтобы отразить, что Java 8 представляет метод String.join().
Что касается соединения, я считаю, что это может показаться немного менее сложным:
public String join (Collection<String> c) {
StringBuilder sb=new StringBuilder();
for(String s: c)
sb.append(s);
return sb.toString();
}
Мне не удается использовать синтаксис Java 5 так часто, как хотелось бы (хотите верьте, хотите нет, в последнее время я использую 1.0.x), так что я, возможно, немного ржавый, но я уверен, что концепция верна .
добавление редактирования: добавление строк может быть медленным, но если вы работаете над кодом графического интерфейса или какой-то непродолжительной рутиной, на самом деле не имеет значения, берете ли вы 0,005 секунды или 0,006, поэтому, если у вас есть коллекция под названием «joinMe» что вы хотите добавить к существующей строке "target", было бы не ужасно просто встроить это:
for(String s : joinMe)
target += s;
Это довольно неэффективно (и плохая привычка), но ничего, что вы сможете понять, если только не тысячи строк, не внутри огромного цикла или ваш код действительно критичен к производительности.
Что еще более важно, это легко запомнить, коротко, быстро и легко читается. Производительность не всегда является автоматическим победителем при выборе дизайна.
Цикл for правильный, но вы также должны сделать его Collection <String>. Если вы этого не сделаете, вам придется сказать «for (Object o: c)», потому что вы не можете гарантировать, что все в c было строкой.
Хорошая мысль, я еще более ржавый с Generics. Отредактирую в.
При объединении inline: string + string + string компилятор фактически использует StringBuilder для добавления значений. Интересно, если в методе for-loop у вас есть второй, сделает ли компилятор то же самое.
@Spencer K: он использует StringBuilder, но создает новый для каждой итерации (вряд ли самый эффективный метод, но тогда как компилятор должен знать?). Я не знаю, может ли JIT-компилятор оптимизировать это во время выполнения.
Код стиля «цикл и добавление» содержит ошибки, поскольку он излишне применяет произвольное ограничение на входной диапазон его аргументов (на основе общего использования памяти и реализации GC). Этого следует избегать любой ценой, так как никогда не знаешь, когда он тебя укусит.
@soru: не могли бы вы объяснить ошибку? Обычный способ создания большой строки из последовательности частей - «зациклить и добавить». Если вы утверждаете, что вам не следует создавать большие строки, а вместо этого использовать только онлайн-алгоритмы, то вы должны знать, что такие ограничения усложнят вашу программу.
@lan Я думаю, он исходит из другого языка. Использование построителя строк не должно вызывать никаких проблем, и, если у вас не закончится память, не будет ошибок. Если вы использовали конкатенацию строк, у вас могут возникнуть проблемы с памятью, но вы, вероятно, ничего не заметите.
Попробуйте, напишите в обоих направлениях, посмотрите, какой из них позволяет использовать большее значение c.size () без падения.
@soru "Падение"? Если вы имеете в виду нехватку памяти, это не ошибка - просто в одном решении может закончиться нехватка памяти раньше. Я также не уверен, что вы предлагаете в качестве альтернативы. Если альтернатива, которую вы имеете в виду, - это другая библиотека - вы действительно думаете, что она не делает именно этого под листами?
Если код, написанный одним способом (цикл с + =), не работает, а код, написанный другим способом (явный StringBuilder) - нет, то код, написанный таким образом, имеет ошибку. FindBugs помечает это как таковое. Кажется, вы считаете ошибки, связанные с производительностью, не ошибками, хотя на самом деле они - единственное, что хуже ошибок, связанных с потоками. Не существует практического способа даже указать обстоятельства, при которых код неограниченного использования памяти завершится ошибкой.
Ой-подожди. Вы говорите + =? Да, это отстой. В настоящее время цикл и добавление в моем ответе используют StringBuilder, и это то, о чем я говорю. Хотя + = значительно улучшился, вы действительно не хотите использовать его внутри цикла - не столько потому, что он глючит, сколько потому, что он может работать как дерьмо (ошибка - это не термин, обычно используемый для проблем с производительностью - по крайней мере, не за мои 20 лет программирования). Также JIT может значительно улучшить это, но я бы не стал на это полагаться.
Если вы хотите объединить (объединить) несколько строк в одну, вам следует использовать StringBuilder. Это намного лучше, чем использовать
for(String s : joinMe)
target += s;
Также есть небольшое преимущество в производительности над StringBuffer, поскольку StringBuilder не использует синхронизацию.
Для такого универсального служебного метода он (в конечном итоге) будет вызываться много раз во многих ситуациях, поэтому вы должны сделать его эффективным и не выделять много временных объектов. Мы профилировали множество различных приложений Java и почти всегда обнаруживаем, что конкатенация строк и выделение строк / символов [] занимают значительное количество времени / памяти.
Наша многоразовая коллекция -> строковый метод сначала вычисляет размер требуемого результата, а затем создает StringBuilder с этим начальным размером; это позволяет избежать ненужного дублирования / копирования внутреннего char [], используемого при добавлении строк.
re: предварительный расчет размера: Когда это работает, это здорово. Это не всегда возможно. Я помню, как где-то читал, что удвоение размера буфера каждый раз (или действительно умножение на любой фиксированный коэффициент) дает что-то вроде производительности n log n, что на самом деле не так уж и плохо. В общем случае альтернативой является составление списка всех строк, которые вы планируете объединить. Если вы используете ArrayList, у вас снова есть копирование (если вы заранее не знаете длину своей последовательности), а если вы используете LinkedList, тогда он использует больше памяти и сборку мусора с объектами узлов. Иногда не получается победить. Попробуй!
Приведенные выше примеры / запросы предполагали некоторую упорядоченную коллекцию или массив строк для объединения. Кроме того, предварительно вычисляя размер, вы избегаете лишних неиспользуемых символов, к которым обычно приводит рост внутреннего массива char [].
StringUtils - довольно полезный класс в библиотеке Apache Commons Lang.
Возможно, вы не заметили, что принятый ответ, опубликованный 8 месяцев назад, уже содержит ту же информацию; stackoverflow.com/questions/187676/string-operations-in-java /…
Я бы просто использовал оператор конкатенации строк «+» для соединения двух строк. s1 += s2;
Потому что это плохая практика и медлительность.
Вы также можете использовать переменные аргументы для строк следующим образом:
String join (String delim, String ... data) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.length; i++) {
sb.append(data[i]);
if (i >= data.length-1) {break;}
sb.append(delim);
}
return sb.toString();
}
Я написал собственное:
public static String join(Collection<String> col, String delim) {
StringBuilder sb = new StringBuilder();
Iterator<String> iter = col.iterator();
if (iter.hasNext())
sb.append(iter.next().toString());
while (iter.hasNext()) {
sb.append(delim);
sb.append(iter.next().toString());
}
return sb.toString();
}
но Collection не поддерживается JSP, поэтому для функции тега я написал:
public static String join(List<?> list, String delim) {
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++) {
sb.append(delim);
sb.append(list.get(i).toString());
}
return sb.toString();
}
и поместите в файл .tld:
<?xml version = "1.0" encoding = "UTF-8"?>
<taglib version = "2.1" xmlns = "http://java.sun.com/xml/ns/javaee"
<function>
<name>join</name>
<function-class>com.core.util.ReportUtil</function-class>
<function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature>
</function>
</taglib>
и используйте его в файлах JSP как:
<%@taglib prefix = "funnyFmt" uri = "tag:com.core.util,2013:funnyFmt"%>
${funnyFmt:join(books, ", ")}
TextUtils.join доступен на Android
ArrayList<Double> j=new ArrayList<>;
j.add(1);
j.add(.92);
j.add(3);
String ntop=j.toString(); //ntop= "[1, 0.92, 3]"
Таким образом, String ntop хранит значение всей коллекции с разделителями-запятыми и скобками.
Я не уверен, на какую часть вопроса это отвечает? Это не String.format, если вы не планируете добавлять биты строки в массив побитно, а [1,0.92,3] не так универсален, как обычная строка .join.
Начиная с Java 8, join() теперь доступен как два метода класса в классе String. В обоих случаях первым аргументом является разделитель.
Вы можете передавать отдельные CharSequence в качестве дополнительных аргументов:
String joined = String.join(", ", "Antimony", "Arsenic", "Aluminum", "Selenium");
// "Antimony, Arsenic, Alumninum, Selenium"
Или вы можете пройти Iterable<? extends CharSequence>:
List<String> strings = new LinkedList<String>();
strings.add("EX");
strings.add("TER");
strings.add("MIN");
strings.add("ATE");
String joined = String.join("-", strings);
// "EX-TER-MIN-ATE"
В Java 8 также добавлен новый класс StringJoiner, который можно использовать следующим образом:
StringJoiner joiner = new StringJoiner("&");
joiner.add("x=9");
joiner.add("y=5667.7");
joiner.add("z=-33.0");
String joined = joiner.toString();
// "x=9&y=5667.7&z=-33.0"
Я не хотел импортировать всю библиотеку Apache, чтобы добавить простую функцию соединения, поэтому вот мой совет.
public String join(String delim, List<String> destinations) {
StringBuilder sb = new StringBuilder();
int delimLength = delim.length();
for (String s: destinations) {
sb.append(s);
sb.append(delim);
}
// we have appended the delimiter to the end
// in the previous for-loop. Let's now remove it.
if (sb.length() >= delimLength) {
return sb.substring(0, sb.length() - delimLength);
} else {
return sb.toString();
}
}
@MrSnowflake Есть ли в стандартном построителе строк метод removeCharAt (int index). Он не отображается в версии, которую я использую
@NSjonas - да, его редактирование моего ответа неверно. removeCharAt не существует, и вся функция больше не возвращает String ... Исправлю это.
пока вы в нем ... это текущее решение вызовет «исключение индекса за пределами границ, если вы передадите пустой список»
внесены изменения, чтобы обрезать правильную длину разделителя более 1 символа. Также исправлена проблема, из-за которой вы обрезали последний символ, а не первый, как вам действительно нужно.
Спасибо за отзыв. Обновлено.
Приношу свои извинения, это не removeCharAt(int index), а deleteCharAt(int). Но у него такой же функционал.
Вот довольно простой ответ. Используйте +=, так как это меньше кода, и пусть оптимизатор конвертирует его в StringBuilder за вас. Используя этот метод, вам не нужно выполнять никаких проверок «последний» в вашем цикле (улучшение производительности), и вам не нужно беспокоиться об удалении каких-либо разделителей в конце.
Iterator<String> iter = args.iterator();
output += iter.hasNext() ? iter.next() : "";
while (iter.hasNext()) {
output += "," + iter.next();
}
Очень элегантное решение, без сторонних библиотек!
Я вижу здесь много слишком сложных реализаций String.Join. Если у вас нет Java 1.8 и вы не хотите импортировать новую библиотеку, реализации ниже должно быть достаточно.
public String join(Collection<String> col, String delim) {
StringBuilder sb = new StringBuilder();
for ( String s : col ) {
if ( sb.length() != 0 ) sb.append(delim);
sb.append(s);
}
return sb.toString();
}
Итак, есть String.format, но мне придется откатить собственное соединение.