Я ищу метод для объединения массива строк в разделенную строку. Противоположность split().
Хотел спросить форум, прежде чем я попытаюсь написать свой собственный (так как в JDK есть все)
Я ищу метод для объединения массива строк в разделенную строку. Противоположность split().
Хотел спросить форум, прежде чем я попытаюсь написать свой собственный (так как в JDK есть все)
В JDK нет такого метода, о котором я знаю. Apache Commons Lang имеет различные перегруженные методы join() в StringUtils, которые делают то, что вы хотите.
С момента появления, по крайней мере, 2009 года был запрошен открытый запрос. Достаточно долгое, что он будет частью функциональности класса JDK 8 java.util.StringJoiner. http://download.java.net/lambda/b81/docs/api/java/util/StringJoiner.html
Вот проблема Oracle, если вы заинтересованы. http://bugs.sun.com/view_bug.do?bug_id=5015163
Вот пример нового JDK 8 StringJoiner в массиве String
String[] a = new String[]{"first","second","third"};
StringJoiner sj = new StringJoiner(",");
for(String s:a) sj.add(s);
System.out.println(sj); //first,second,third
Утилита в String делает это еще проще:
String s = String.join(",", stringArray);
Вы можете скрывать эту функциональность из служебного пакета Arrays.
import java.util.Arrays;
...
    String  delim = ":",
            csv_record = "Field0:Field1:Field2", 
            fields[] = csv_record.split(delim);
    String rebuilt_record = Arrays.toString(fields).replace(", ", delim).replaceAll("[\\[\\]]", "");
Я получил следующий пример здесь
/*
7) Join Strings using separator >>>AB$#$CD$#$EF
 */
import org.apache.commons.lang.StringUtils;
public class StringUtilsTrial {
  public static void main(String[] args) {
    // Join all Strings in the Array into a Single String, separated by $#$
    System.out.println("7) Join Strings using separator >>>"
        + StringUtils.join(new String[] { "AB", "CD", "EF" }, "$#$"));
  }
}
Google также предоставляет класс столяров в своей библиотеке Google Collections:
Есть несколько примеров в DZone Snippets, если вы хотите перевернуть свой собственный, который работает с коллекцией. Например:
public static String join(AbstractCollection<String> s, String delimiter) {
    if (s == null || s.isEmpty()) return "";
    Iterator<String> iter = s.iterator();
    StringBuilder builder = new StringBuilder(iter.next());
    while( iter.hasNext() )
    {
        builder.append(delimiter).append(iter.next());
    }
    return builder.toString();
}
Если у вас есть int [], Arrays.toString() - самый простой способ.
Основываясь на всех предыдущих ответах:
public static String join(Iterable<? extends Object> elements, CharSequence separator) 
{
    StringBuilder builder = new StringBuilder();
    if (elements != null)
    {
        Iterator<? extends Object> iter = elements.iterator();
        if(iter.hasNext())
        {
            builder.append( String.valueOf( iter.next() ) );
            while(iter.hasNext())
            {
                builder
                    .append( separator )
                    .append( String.valueOf( iter.next() ) );
            }
        }
    }
    return builder.toString();
}
Для Android: в android.text.TextUtils существуют методы:
public static String join (CharSequence delimiter, Iterable tokens)
public static String join (CharSequence delimiter, Object[] tokens)
Возвращает строку, содержащую маркеры, соединенные разделителями.
tokens - объекты массива, подлежащие объединению. Строки будут сформированы из объектов, вызывая object.toString().
Это тоже неплохо:
public static String join(String delimitor,String ... subkeys) {
    String result = null;
    if(null!=subkeys && subkeys.length>0) {
        StringBuffer joinBuffer = new StringBuffer(subkeys[0]);
        for(int idx=1;idx<subkeys.length;idx++) {
            joinBuffer.append(delimitor).append(subkeys[idx]);
        }
        result = joinBuffer.toString();
    }
    return result;
}
Я написал это:
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());
    while (iter.hasNext()) {
        sb.append(delim);
        sb.append(iter.next());
    }
    return sb.toString();
}
 Collection не поддерживается JSP, поэтому для TLD я написал:
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, ", ")}
Для полноты я хотел бы добавить, что вы не можете отменить String # split в целом, поскольку он принимает регулярное выражение.
 "hello__world".split("_+"); Допустимые значения ["hello", "world"]. "hello_world".split("_+"); Допустимые значения ["hello", "world"].
Они дают идентичные результаты из другой начальной точки. расщепление не является взаимно однозначной операцией и, следовательно, не обратимо.
Все сказанное, если вы считаете, что ваш параметр является фиксированной строкой, а не регулярным выражением, вы можете сделать это, используя один из многих опубликованных ответов.
Ниже приведено базовое представление. Это не лучшее решение.
public static String splitJoin(String sourceStr, String delim,boolean trim,boolean ignoreEmpty){
    return join(Arrays.asList(sourceStr.split(delim)), delim, ignoreEmpty);
}
public static String join(List<?> list, String delim, boolean ignoreEmpty) {
    int len = list.size();
    if (len == 0)
        return "";
    StringBuilder sb = new StringBuilder(list.get(0).toString());
    for (int i = 1; i < len; i++) {
        if (ignoreEmpty && !StringUtils.isBlank(list.get(i).toString())) {
            sb.append(delim);
            sb.append(list.get(i).toString().trim());
        }
    }
    return sb.toString();
}
С JDK8 я очень люблю Streams и Lambdas, поэтому я бы предложил:
public static String join( String delimiter, String[] array )
{
    return Arrays.asList( array ).stream().collect( Collectors.joining( delimiter ) );
}
Мне нравится это лучше:
public String join(Collection<String> strCollection, String delimiter) {
    String joined = "";
    int noOfItems = 0;
    for (String item : strCollection) {
        joined += item;
        if (++noOfItems < strCollection.size())
            joined += delimiter;
    }
    return joined;
}
Это лучшее решение, которое я нашел до сих пор. (Не беспокойтесь об использовании исходных объектов String вместо StringBuilder. Современные компиляторы Java используют StringBuilder в любом случае, но этот код более читабельен).
Если вы используете jdk8, см. @Nathaniel Johnson answer, так как это лучше.
Я думаю, что многие из ответов здесь сложны или легко читаются. С предсказанием ветвления настолько эффективно, что вы просто не используете оператор if?
public static String join(List<String> fooList){
    if (fooList.isEmpty()) return "";
    StringBuilder sb = null;
    for (String element : fooList) {
        if (sb == null) {
            sb = new StringBuilder();
        } else {
            sb.append(", ");
        }
        sb.append(element);
    }
    return sb.toString();
}
Что-то, о чем следует упомянуть, заключается в том, что Apache использует простой цикл for с выражением if внутри него, как это (он использует массив как свой индекс, чтобы знать первый элемент), а openjdk 8 делает то же самое, но в разделенных методах вместо простого цикла.