Быстрый и простой способ объединения элементов массива с разделителем (противоположность split) в Java

См. Связанный .NET вопрос

Я ищу быстрый и простой способ сделать прямо противоположное расколу так что это приведет к тому, что ["a","b","c"] станет "a,b,c"

Итерация через массив требует либо добавления условия (если это не последний элемент, добавить разделитель), либо использовать подстроку для удаления последнего разделителя.

Я уверен, что есть сертифицированный, эффективный способ сделать это (Apache Commons?)

Как вы предпочитаете делать это в своих проектах?

Ответ 1

Используя Java 8, вы можете сделать это очень просто:

String.join(delimiter, elements);

Это работает тремя способами:

1), непосредственно определяя элементы

String joined1 = String.join(",", "a", "b", "c");

2) с использованием массивов

String[] array = new String[] { "a", "b", "c" };
String joined2 = String.join(",", array);

3) с использованием итераций

List<String> list = Arrays.asList(array);
String joined3 = String.join(",", list);

Ответ 3

Я предпочитаю Коллекции Google через Apache StringUtils для этой конкретной проблемы:

Joiner.on(separator).join(array)

По сравнению с StringUtils, API-интерфейс Joiner имеет простую конструкцию и немного более гибкий, например. Элементы null могут быть пропущены или заменены заполнителем. Кроме того, Joiner имеет функцию объединения карт с разделителем между ключом и значением.

Ответ 4

Apache Commons Lang действительно имеет StringUtils.join, который будет подключать массивы String вместе с указанным разделителем.

Например:

String[] s = new String[] {"a", "b", "c"};
String joined = StringUtils.join(s, ",");  // "a,b,c"

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

Если бы я должен был выполнить присоединение String, и у меня не было других причин использовать Commons Lang, я бы, вероятно, включил свой собственный, чтобы уменьшить количество зависимостей для внешних библиотек.

Ответ 5

Быстрое и простое решение без участия третьей стороны.

public static String strJoin(String[] aArr, String sSep) {
    StringBuilder sbStr = new StringBuilder();
    for (int i = 0, il = aArr.length; i < il; i++) {
        if (i > 0)
            sbStr.append(sSep);
        sbStr.append(aArr[i]);
    }
    return sbStr.toString();
}

Ответ 7

С Java 1.8 существует новый класс StringJoiner - так что нет необходимости в Guava или Apache Commons:

String str = new StringJoiner(",").add("a").add("b").add("c").toString();

Или используя коллекцию непосредственно с новым потоком api:

String str = Arrays.asList("a", "b", "c").stream().collect(Collectors.joining(","));

Ответ 8

Еще проще использовать массивы, поэтому вы получите строку со значениями массива, разделенными ","

String concat = Arrays.toString(myArray);

чтобы вы закончили с этим: concat = "[a, b, c]"

Обновление

Затем вы можете избавиться от скобок, используя подстроку, как предложено Jeff

concat = concat.substring(1, concat.length() -1);

чтобы вы закончили с concat = "a, b, c"

Ответ 9

Вы можете использовать replace и replaceAll с регулярными выражениями.

String[] strings = {"a", "b", "c"};

String result = Arrays.asList(strings).toString().replaceAll("(^\\[|\\]$)", "").replace(", ", ",");

Потому что Arrays.asList().toString() производит: "[a, b, c]", мы делаем replaceAll для удаления первого и последнего скобок, а затем (необязательно) вы можете изменить последовательность "," для "," ( ваш новый разделитель).

Разделенная версия (меньше символов):

String[] strings = {"a", "b", "c"};

String result = ("" + Arrays.asList(strings)).replaceAll("(^.|.$)", "").replace(", ", "," );

Регулярные выражения очень мощные, особенно методы String "replaceFirst" и "replaceAll". Попробуйте.

Ответ 10

Все эти другие ответы включают служебные данные времени выполнения... например, использование ArrayList.toString(). replaceAll (...), которые очень расточительны.

Я дам вам оптимальный алгоритм с нулевыми служебными данными; он выглядит не так красиво, как другие варианты, но внутри, это то, что они все делают (после груды других скрытых проверок, множественного распределения массивов и других crud).

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

public static String join(String separator, String ... values) {
  if (values.length==0)return "";//need at least one element
  //all string operations use a new array, so minimize all calls possible
  char[] sep = separator.toCharArray();

  // determine final size and normalize nulls
  int totalSize = (values.length - 1) * sep.length;// separator size
  for (int i = 0; i < values.length; i++) {
    if (values[i] == null)
      values[i] = "";
    else
      totalSize += values[i].length();
  }

  //exact size; no bounds checks or resizes
  char[] joined = new char[totalSize];
  int pos = 0;
  //note, we are iterating all the elements except the last one
  for (int i = 0, end = values.length-1; i < end; i++) {
    System.arraycopy(values[i].toCharArray(), 0, 
      joined, pos, values[i].length());
    pos += values[i].length();
    System.arraycopy(sep, 0, joined, pos, sep.length);
    pos += sep.length;
  }
  //now, add the last element; 
  //this is why we checked values.length == 0 off the hop
  System.arraycopy(values[values.length-1].toCharArray(), 0,
    joined, pos, values[values.length-1].length());

  return new String(joined);
}

Ответ 11

Эти параметры быстрые и понятные:

  public static String join(String separator, String... values) {
    StringBuilder sb = new StringBuilder(128);
    int end = 0;
    for (String s : values) {
      if (s != null) {
        sb.append(s);
        end = sb.length();
        sb.append(separator);
      }
    }
    return sb.substring(0, end);
  }

Ответ 13

Эта небольшая функция всегда пригодится.

public static String join(String[] strings, int startIndex, String separator) {
    StringBuffer sb = new StringBuffer();
    for (int i=startIndex; i < strings.length; i++) {
        if (i != startIndex) sb.append(separator);
        sb.append(strings[i]);
    }
    return sb.toString();
}

Ответ 14

Подход, который я принял, развился с версии Java 1.0, чтобы обеспечить читаемость и поддерживать разумные варианты обратной совместимости со старыми версиями Java, а также предоставлять сигнатуры методов, которые заменяют замену для пользователей apache commons-lang. По соображениям производительности, я вижу некоторые возможные возражения против использования Arrays.asList, но я предпочитаю вспомогательные методы, которые имеют разумные значения по умолчанию, не дублируя один метод, который выполняет фактическую работу. Этот подход обеспечивает соответствующие точки входа для надежного метода, который не требует преобразований массива/списка до вызова.

Возможные варианты совместимости версий Java включают подстановку StringBuffer (Java 1.0) для StringBuilder (Java 1.5), выключение итератора Java 1.5 и удаление общего шаблона (Java 1.5) из Collection (Java 1.2). Если вы хотите сделать обратную совместимость еще на один-два этапа, удалите методы, которые используют Collection, и переместите логику в метод на основе массива.

public static String join(String[] values)
{
    return join(values, ',');
}

public static String join(String[] values, char delimiter)
{
    return join(Arrays.asList(values), String.valueOf(delimiter));
}

// To match Apache commons-lang: StringUtils.join(values, delimiter)
public static String join(String[] values, String delimiter)
{
    return join(Arrays.asList(values), delimiter);
}

public static String join(Collection<?> values)
{
    return join(values, ',');
}

public static String join(Collection<?> values, char delimiter)
{
    return join(values, String.valueOf(delimiter));
}

public static String join(Collection<?> values, String delimiter)
{
    if (values == null)
    {
        return new String();
    }

    StringBuffer strbuf = new StringBuffer();

    boolean first = true;

    for (Object value : values)
    {
        if (!first) { strbuf.append(delimiter); } else { first = false; }
        strbuf.append(value.toString());
    }

    return strbuf.toString();
}

Ответ 15

public String join(String[] str, String separator){
    String retval = "";
    for (String s: str){ retval+= separator + s;}
    return retval.replaceFirst(separator, "");
}