Java: объединить массив примитивов с разделителем

Предположим, у меня есть массив:

int[] arr = new int[] {1, 2, 3, 4, 5, 6, 7};

И мне нужно объединить его элементы с помощью разделителя, например, " - "в результате я должен получить строку вроде этой:

"1 - 2 - 3 - 4 - 5 - 6 - 7"

Как я мог это сделать?

PS: да, я знаю об этом и этом постах, но его решения не будут работать с массивом примитивов.

6 ответов

Решение

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


С помощью StringUtils а также ArrayUtils из общего языка:

int[] arr = new int[] {1, 2, 3, 4, 5, 6, 7};
String result = StringUtils.join(ArrayUtils.toObject(arr), " - ");

Вы не можете просто использовать StringUtils.join(arr, " - "); так как StringUtils нет перегруженной версии метода. Хотя, у него есть метод StringUtils.join(int[], char),

Работает на любой версии Java, начиная с 1.2.


Использование потоков Java 8:

Что-то вроде этого:

int[] arr = new int[] {1, 2, 3, 4, 5, 6, 7};
String result = Arrays.stream(arr)
        .mapToObj(String::valueOf)
        .collect(Collectors.joining(" - "));

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

Метод Java 8 String.join() работает только со строками, поэтому для его использования необходимо преобразовать int[] в String[],

String[] sarr = Arrays.stream(arr).mapToObj(String::valueOf).toArray(String[]::new);
String result = String.join(" - ", sarr);

Если вы придерживались Java 7 или более ранней версии без библиотек, вы можете написать свой собственный служебный метод:

public static String myJoin(int[] arr, String separator) {
    if (null == arr || 0 == arr.length) return "";

    StringBuilder sb = new StringBuilder(256);
    sb.append(arr[0]);

    //if (arr.length == 1) return sb.toString();

    for (int i = 1; i < arr.length; i++) sb.append(separator).append(arr[i]);

    return sb.toString();
}

Чем вы можете сделать:

int[] arr = new int[] {1, 2, 3, 4, 5, 6, 7};
String result = myJoin(arr, " - ");

Решение Java 8 будет выглядеть так:

Stream.of(1,2,3,4).map(String::valueOf).collect(Collectors.joining("-"))

В Java 8+ вы можете использовать IntStream и StringJoiner, Что-то вроде,

int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7 };
StringJoiner sj = new StringJoiner(" - ");
IntStream.of(arr).forEach(x -> sj.add(String.valueOf(x)));
System.out.println(sj.toString());

Вывод (по запросу)

1 - 2 - 3 - 4 - 5 - 6 - 7

Вы можете использовать гуаву для соединения элементов. Больше примеров и документов вы можете найти там. https://github.com/google/guava/wiki/StringsExplained

Joiner.on("-")
      .join(texts);

Чтобы быть более точным, вы должны сначала обернуть ваш массив в List с Arrays.asList() или примитивно-дружественные эквиваленты Гуавы.

Joiner.on("-")
      .join(Arrays.asList(1, 2, 3, 4, 5, 6, 7));

Joiner.on("-")
      .join(Ints.asList(arr));
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7 };

IntStream.of(arr).mapToObj(i -> String.valueOf(i)).collect(Collectors.joining(",")) ;

Я уверен, что есть способ сделать это на Kotlin/Scala или на других языках JVM, но вы всегда можете придерживаться простых правил для небольшого набора значений, как у вас было выше:

int i, arrLen = arr.length;
 StringBuilder tmp = new StringBuilder();
 for (i=0; i<arrLen-1; i++)
    tmp.append(arr[i] +" - ");
 tmp.append(arr[arrLen-1]);

 System.out.println( tmp.toString() );

Если ваш разделитель представляет собой один символ, вы можете использовать StringUtils из Common Lang:

int[] arr = {1, 2, 3, 4, 5, 6, 7};
String result = StringUtils.join(arr, '-');

Однако, если разделителем является строка, вы должны использовать альтернативу, потому что StringUtils ведет себя плохо (см. Этот билет).

Для Java 7 или более ранней версии.

public static StringBuilder join(CharSequence delimiter, int... arr) {
    if (null == delimiter || null == arr) throw new NullPointerException();

    StringBuilder sb = new StringBuilder(String.valueOf(arr[0]));
    for (int i = 1; i < arr.length; i++) sb.append(delimiter).append(arr[i]);

    return sb;
}

public static void main(String[] args) {
    StringBuilder sb = join(" - ", 1, 2, 3, 4);
    System.out.println(sb.toString());//you could pass sb also coz println automatically call toString method within it
    System.out.println(sb.insert(0, "[").append("]"));
}

Выход:

1-2-3-4

[1–2–3–4]

Я искал способ присоединения примитивов в потоке без предварительного создания строк для каждого из них. Я пришел к этому, но он все еще требует бокса их.

LongStream.range(0, 500).boxed().collect(Collector.of(StringBuilder::new, (sb, v) -> {
    if (sb.length() != 0)
        sb.append(',');
    sb.append(v.longValue());
}, (a, b) -> a.length() == 0 ? b : b.length() != 0 ? a.append(',').append(b) : a, StringBuilder::toString));

В java8 вы можете использовать класс String как:

String joined = String.join(",", name);
Другие вопросы по тегам