Метод обратного эффекта java String.split()?

Я ищу метод для объединения массива строк в разделенную строку. Противоположность split().

Хотел спросить форум, прежде чем я попытаюсь написать свой собственный (так как в JDK есть все)

Ответ 1

В JDK нет такого метода, о котором я знаю. Apache Commons Lang имеет различные перегруженные методы join() в StringUtils, которые делают то, что вы хотите.

Ответ 2

С момента появления, по крайней мере, 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

Update

Вот пример нового 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);

Ответ 3

Вы можете скрывать эту функциональность из служебного пакета 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("[\\[\\]]", "");

Ответ 4

Я получил следующий пример здесь

/*
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" }, "$#$"));
  }
}

Ответ 6

Есть несколько примеров в 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();
}

Ответ 7

Если у вас есть int [], Arrays.toString() - самый простой способ.

Ответ 8

Основываясь на всех предыдущих ответах:

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();
}

Ответ 9

Для Android: в android.text.TextUtils существуют методы:

public static String join (CharSequence delimiter, Iterable tokens)
public static String join (CharSequence delimiter, Object[] tokens)

Возвращает строку, содержащую маркеры, соединенные разделителями.

tokens - объекты массива, подлежащие объединению. Строки будут сформированы из объектов, вызывая object.toString().

Ответ 10

Это тоже неплохо:

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;
}

Ответ 11

Я написал это:

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, ", ")}

Ответ 12

Для полноты я хотел бы добавить, что вы не можете отменить String # split в целом, поскольку он принимает регулярное выражение.

"hello__world".split("_+"); Допустимые значения ["hello", "world"].
"hello_world".split("_+"); Допустимые значения ["hello", "world"].

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

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

Ответ 13

Ниже приведено базовое представление. Это не лучшее решение.

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();
}

Ответ 14

С JDK8 я очень люблю Streams и Lambdas, поэтому я бы предложил:

public static String join( String delimiter, String[] array )
{
    return Arrays.asList( array ).stream().collect( Collectors.joining( delimiter ) );
}

Ответ 15

Мне нравится это лучше:

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 в любом случае, но этот код более читабельен).

Ответ 16

Если вы используете 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 делает то же самое, но в разделенных методах вместо простого цикла.