Java: функция для массивов, таких как PHP join ()?


259

Я хочу присоединиться String[]к клейкой ленте. Есть ли функция для этого?


7
В Java 8 эта функциональность включена из коробки. Я рекомендую читателю прокрутить до ответа @Marek Gregor (и поднять его голос ..)
Став

Ответы:


307

Начиная с Java8 можно использовать String.join().

String.join(", ", new String[]{"Hello", "World", "!"})

Формирует:

Hello, World, !

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

Например:

StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")

Создает следующее String:

Hello, World, !

7
Для удобства людей, ищущих этот ответ, вероятно, следует отметить, что это также эквивалент Perl-соединения.
К-ден,

3
он говорит, что это не определено для меня
Ninjaxor

@Ninjaxor 1. commons-lang * jar должен находиться в пути к классам 2. import org.apache.commons.lang3.StringUtils;
Петер - Восстановить Монику

9
Я бы порекомендовал вам отредактировать этот ответ, чтобы добавить ссылку на новый String.join()метод, введенный в Java 8. Таким образом, огромное количество людей, читающих этот принятый ответ, получат пользу от этих знаний. В настоящее время ответ, получивший наибольшее количество голосов с упоминанием этого факта, скорее всего потерян ниже ...
Дункан Джонс

1
Стоит отметить , что String.join()будет работать только List<CharSequence>или CharSequence[]элементы.
Enigo

71

Если вы искали, что использовать в Android, это:

String android.text.TextUtils.join(CharSequence delimiter, Object[] tokens)

например:

String joined = TextUtils.join(";", MyStringArray);

2
Это, безусловно, лучший ответ для всех версий Android, так как Java 8 выйдет на Android чуть позже. В этом решении используются встроенные библиотеки Android, а не эти глупые решения «включить огромную библиотеку для выполнения одного действия».
LukeStoneHm

Это сентябрь 2017 года, Java 8 для Android еще далеко. Спасибо за этот ответ!
Aenadon


53

Вы можете легко написать такую ​​функцию примерно в десяти строках кода:

String combine(String[] s, String glue)
{
  int k = s.length;
  if ( k == 0 )
  {
    return null;
  }
  StringBuilder out = new StringBuilder();
  out.append( s[0] );
  for ( int x=1; x < k; ++x )
  {
    out.append(glue).append(s[x]);
  }
  return out.toString();
}

35
Хорошая практика, по вашему мнению, не существует универсального стандарта для таких вещей.
Феб

24
Но если бы я включил фигурные скобки, это добавило бы еще две строки кода, и я бы не сказал, что сделал это в 11 строк!
Джей

8
проблема в том, что вы через какое-то время или кто-то другой спешите добавить к этому еще одну строку if / for без добавления скобок; или удалите return null после if (k == 0), который в некоторых случаях будет компилироваться, но будет некорректным. Тогда лучше пожертвовать одну дополнительную строку для этой закрывающей скобки (открытие может остаться в той же самой строке if / for).
Милан

16
Я думаю, это потрясающе, что, хотя большинство языков упаковывают такую ​​функциональность в свое ядро, сообщество Java призывает всех изобретать велосипед.
Джон Стриклер

33
11 строк? Ба! Я могу сделать это в 1! Просто удалите все символы новой строки в исходном файле.
Томас Эдинг

25

Небольшой мод вместо использования substring ():

//join(String array,delimiter)
public static String join(String r[],String d)
{
        if (r.length == 0) return "";
        StringBuilder sb = new StringBuilder();
        int i;
        for(i=0;i<r.length-1;i++){
            sb.append(r[i]);
            sb.append(d);
        }
        sb.append(r[i]);
        return sb.toString();
}

Проголосовал, потому что вам не нужно добавлять какие-либо библиотеки.
Givanse

10
Строка 7: лучше ли использовать .append()два раза для каждого Stringвместо того, чтобы объединить их, а затем добавить к сборщику.
Талха Ахмед Хан

18

Как и многие вопросы в последнее время, Java 8 на помощь:


Java 8 добавил новый статический метод, java.lang.Stringкоторый делает именно то, что вы хотите:

public static String join(CharSequence delimeter, CharSequence... elements);

Используй это:

String s = String.join(", ", new String[] {"Hello", "World", "!"});

Результаты в:

"Hello, World, !"

14

Библиотека Google Guava также имеет такую ​​возможность . Вы можете увидеть пример String [] также из API.

Как уже описано в API, остерегайтесь неизменности методов компоновщика.

Он может принимать массив объектов, поэтому он будет работать в вашем случае. В моем предыдущем опыте я попытался присоединиться к стеку, который является итеративным, и он отлично работает.

Образец от меня:

Deque<String> nameStack = new ArrayDeque<>();
nameStack.push("a coder");
nameStack.push("i am");
System.out.println("|" + Joiner.on(' ').skipNulls().join(nameStack) + "|");

распечатывает: |i am a coder|


9

Дано:

String[] a = new String[] { "Hello", "World", "!" };

Тогда в качестве альтернативы ответу coobird, где клей ",":

Arrays.asList(a).toString().replaceAll("^\\[|\\]$", "")

Или объединить с другой строкой, такой как "& amp;".

Arrays.asList(a).toString().replaceAll(", ", " &amp; ").replaceAll("^\\[|\\]$", "")

Однако ... это ТОЛЬКО работает, если вы знаете, что значения в массиве или списке НЕ содержат символьную строку ",".


Arrays.asList(a).toString()работал для того, что я хотел сделать
Соломон Уцко


8

Не по сути, нет. Поиск «склеивания строк присоединения к массиву Java» даст вам некоторые фрагменты кода о том, как этого добиться.

например

public static String join(Collection s, String delimiter) {
    StringBuffer buffer = new StringBuffer();
    Iterator iter = s.iterator();
    while (iter.hasNext()) {
        buffer.append(iter.next());
        if (iter.hasNext()) {
            buffer.append(delimiter);
        }
    }
    return buffer.toString();
}

2
Используйте StringBuilder (не ориентированный на поток) вместо StringBuffer (ориентированный на поток) для лучшей производительности. Интерфейс такой же.
Асаф

2
Это, кажется, от snippets.dzone.com/posts/show/91 . Комментарии предлагают значительно улучшенную версию: публичное статическое соединение строк (Iterable <? Extends Object> pColl, разделитель строк) {Iterator <? расширяет объект> oIter; if (pColl == null || (! (oIter = pColl.iterator ()) .hasNext ())) return ""; StringBuilder oBuilder = new StringBuilder (String.valueOf (oIter.next ())); while (oIter.hasNext ()) oBuilder.append (разделитель) .append (oIter.next ()); return oBuilder.toString (); }
Quantum7

6

Если вы оказались здесь в поисках быстрого преобразования массива в строку, попробуйте Arrays.toString () .

Создает строковое представление Object[]переданного. Результат "[]"заключен в скобки ( ), каждый элемент преобразуется в строку через String.valueOf(Object)и разделяется ", ". Если массив есть null, то "null"возвращается.


ОГРОМНОЕ СПАСИБО! Строки разделены символом «,», и вокруг всего этого есть «[]», что меня устраивает.
Джон Хенкель

5

Просто для задания «У меня самый короткий» , вот мины;)

Повторяющийся:

public static String join(String s, Object... a) {
    StringBuilder o = new StringBuilder();
    for (Iterator<Object> i = Arrays.asList(a).iterator(); i.hasNext();)
        o.append(i.next()).append(i.hasNext() ? s : "");
    return o.toString();
}

рекурсивные:

public static String join(String s, Object... a) {
    return a.length == 0 ? "" : a[0] + (a.length == 1 ? "" : s + join(s, Arrays.copyOfRange(a, 1, a.length)));
}

2
Рекурсивная версия элегантна. Определенно собираюсь использовать это.
Пит

Рекурсивная версия может быть элегантной, но неэффективной для больших массивов (" copyOfRange()").
Огр Псалом 33

4

Ничего встроенного, что я знаю.

Apache Commons Lang имеет класс с именем, StringUtilsкоторый содержит много функций соединения.


4

Вот как я это делаю.

private String join(String[] input, String delimiter)
{
    StringBuilder sb = new StringBuilder();
    for(String value : input)
    {
        sb.append(value);
        sb.append(delimiter);
    }
    int length = sb.length();
    if(length > 0)
    {
        // Remove the extra delimiter
        sb.setLength(length - delimiter.length());
    }
    return sb.toString();
}

2

Аналогичная альтернатива

/**
 * @param delimiter 
 * @param inStr
 * @return String
 */
public static String join(String delimiter, String... inStr)
{
    StringBuilder sb = new StringBuilder();
    if (inStr.length > 0)
    {
        sb.append(inStr[0]);
        for (int i = 1; i < inStr.length; i++)
        {
            sb.append(delimiter);                   
            sb.append(inStr[i]);
        }
    }
    return sb.toString();
}

2

Мой спин

public static String join(Object[] objects, String delimiter) {
  if (objects.length == 0) {
    return "";
  }
  int capacityGuess = (objects.length * objects[0].toString().length())
      + ((objects.length - 1) * delimiter.length());
  StringBuilder ret = new StringBuilder(capacityGuess);
  ret.append(objects[0]);
  for (int i = 1; i < objects.length; i++) {
    ret.append(delimiter);
    ret.append(objects[i]);
  }
  return ret.toString();
}

public static String join(Object... objects) {
  return join(objects, "");
}

1

Вам нравится мой трехстрочный способ, использующий только методы класса String?

static String join(String glue, String[] array) {
    String line = "";
    for (String s : array) line += s + glue;
    return (array.length == 0) ? line : line.substring(0, line.length() - glue.length());
}

1
Это не значит быть эффективным. Используйте, StringBuilderесли вам нужна эффективность: P
Ryoichiro Oka

0

Чтобы получить "str1, str2" из "str1", "str2", "":

Stream.of("str1", "str2", "").filter(str -> !str.isEmpty()).collect(Collectors.joining(", ")); 

Также вы можете добавить дополнительную нулевую проверку


0

Если вы используете функциональную библиотеку Java и по какой-то причине не можете использовать потоки из Java 8 (что может иметь место при использовании плагина Android + Retrolambda), вот функциональное решение для вас:

String joinWithSeparator(List<String> items, String separator) {
    return items
            .bind(id -> list(separator, id))
            .drop(1)
            .foldLeft(
                    (result, item) -> result + item,
                    ""
            );
}

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


-1

Я делаю это таким образом, используя StringBuilder:

public static String join(String[] source, String delimiter) {
    if ((null == source) || (source.length < 1)) {
        return "";
    }

    StringBuilder stringbuilder = new StringBuilder();
    for (String s : source) {
        stringbuilder.append(s + delimiter);
    }
    return stringbuilder.toString();
} // join((String[], String)

1
s + delimiter(конкатенация строк с оператором "плюс") отрицает всю цель использования StringBuilder.
спокойная мята

Кроме того, этот подход будет означать, что массив вроде: {"foo", "bar"} с разделителем ":" будет превращен в "foo: bar:"
pioto

-2

В большинстве случаев я использую простую технику записи.

String op = new String;
for (int i : is) 
{
    op += candidatesArr[i-1]+",";
}
op = op.substring(0, op.length()-1);

Это работает только с разделителями длины 1 и требует «магических чисел» (хотя и достаточно локальных), если вы хотели разделитель другой длины.
Майвальд

Вы можете добавить несколько символов при добавлении
Гаурав Адуркар

чем просто сделать: op = op.substring (0, op.length () - ",". length ()); подумаешь?
Деннис

-3

В java.util.Arrays есть метод asList. Вместе с API java.util.List / ArrayList это дает вам все необходимое :;

private static String[] join(String[] array1, String[] array2) {

    List<String> list = new ArrayList<String>(Arrays.asList(array1));
    list.addAll(Arrays.asList(array2));
    return list.toArray(new String[0]);
}

7
Вопрос в том, как объединить массив строк с разделителем, а не в том, как соединить два массива строк вместе.
toolbear
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.