Самый ясный способ запятых-разделять список?
каков самый ясный способ разделять список запятыми в 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());
}
эти обрабатывают первый деталь специально; одно смогло вместо обработать последнее одно специально.
Кстати, вот как ListtoStringи реализовано (наследуется от 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 имеют intersperse - как это это реализованы?).
уточнение: под библиотеками я подразумеваю стандартные библиотеки Java. Для других библиотек я рассматриваю их с другими языками и интересуюсь, как они работают выполненный.
EDIT toolkit упомянул аналогичный вопрос: последняя итерация расширенного цикла for в java
и еще:
Заслуживает ли последний элемент цикла отдельного рассмотрения?
30 ответов:
для pre Java-8:
см. также #285523
String delim = ""; for (Item i : list) { sb.append(delim).append(i); delim = ","; }
обновление с Java 8:
используя StringJoiner:
StringJoiner joiner = new StringJoiner(","); for (Item item : list) { joiner.add(item.toString()); } return joiner.toString();используя поток и коллекторами:
return list.stream(). map(Object::toString). collect(Collectors.joining(",")).toString();
в Java 8 предоставляет несколько новых способов сделать это:
- The
joinметод onString.- A
joiningколлектор для потоков отCollectorsкласса.- The
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(i -> i.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;.
на основе реализации Java List toString:
Iterator i = list.iterator(); for (;;) { sb.append(i.next()); if (! i.hasNext()) break; ab.append(", "); }он использует грамматику, как это:
List --> (Item , )* Itemбудучи последним на основе вместо первого на основе, он может проверить пропуск запятой с тем же тестом, чтобы проверить конец списка. Я думаю, что это очень элегантно, но я не уверен в ясности.
Если вы используете 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)
String delimiter = ","; StringBuilder sb = new StringBuilder(); for (Item i : list) { sb.append(delimiter).append(i); } sb.toString().replaceFirst(delimiter, "");
есть довольно способ добиться этого с помощью Java 8:
List<String> list = Arrays.asList(array); String joinedString = String.join(",", list);
один из вариантов для цикла foreach является:
StringBuilder sb = new StringBuilder(); for(String s:list){ if (sb.length()>0) sb.append(","); sb.append(s); }
StringBuffer result = new StringBuffer(); for(Iterator it=list.iterator; it.hasNext(); ) { if (result.length()>0) result.append(", "); result.append(it.next()); }обновление: как упоминал Дэйв Уэбб в комментариях, это может не дать правильных результатов, если первые элементы в списке являются пустыми строками.
Я обычно делаю так :
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;)
Если вы можете использовать Groovy (который работает на JVM):
def list = ['a', 'b', 'c', 'd'] println list.join(',')
(копипаст моего ответа из здесь.) Многие из описанных здесь решений немного перегружены, IMHO, особенно те, которые полагаются на внешние библиотеки. Существует хорошая чистая, ясная идиома для достижения списка, разделенного запятыми, который я всегда использовал. Он полагается на условное (?) оператор:
Edit: оригинальное решение правильное, но не оптимальное по комментариям. Попытка во второй раз:
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.
2-е изд: если вы имеете дело с итератором:
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() ? "," : "");
Я не компилировал его... но должен работать (или быть близко к работе).
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()); }
StringBuffer sb = new StringBuffer(); for (int i = 0; i < myList.size(); i++) { if (i > 0) { sb.append(", "); } sb.append(myList.get(i)); }
мне несколько нравится этот подход, который я нашел в блоге некоторое время назад. К сожалению, я не помню имя/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); }
потому что ваш разделитель ", " вы можете использовать любой из следующих:
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;} } }Если ваш разделитель что-нибудь еще, то это не будет работать для вас.
Мне нравится такое решение:
String delim = " - ", string = ""; for (String item : myCollection) string += delim + item; string = string.substring(delim.length());Я предполагаю, что он может использовать StringBuilder тоже.
в Python его легко
",".join (yourlist )
в C# есть статический метод для класса String
строку.Join (",", yourlistofstrings)
извините, не уверен в Java, но думал, что я буду трубить, как вы спросили о других языках. Я уверен, что было бы что-то подобное в Java.
вы также можете безоговорочно добавить строку разделителя, а после цикла удалить дополнительный разделитель в конце. Тогда "если список пуст, то вернуть эту строку" в начале позволит избежать проверки в конце (так как вы не можете удалить символы из пустого списка)
Так что вопрос действительно таков:
"учитывая петлю и если, что вы думаете, это самый ясный способ иметь их вместе?"
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; }
if (array.length>0) // edited in response Joachim's comment sb.append(array[i]); for (int i=1; i<array.length; i++) sb.append(",").append(array[i]);на основе самый ясный способ запятая-разделять список (Java)?
используя эту идею: заслуживает ли последний элемент цикла отдельного рассмотрения?
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(); }
ни один из ответов не использует рекурсию до сих пор...
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, ',')); } }
на мой взгляд, это самый простой для чтения и понимания:
StringBuilder sb = new StringBuilder(); for(String string : strings) { sb.append(string).append(','); } sb.setLength(sb.length() - 1); String result = sb.toString();
private String betweenComma(ArrayList<String> strings) { String united = ""; for (String string : strings) { united = united + "," + string; } return united.replaceFirst(",", ""); }
метод
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
Comments