Java
Array Manipulation
String Joining
Programming Tips
Code Optimization

A quick and easy way to join array elements with a separator (the opposite of split) in Java

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The opposite of splitting a string is joining values together with a separator. In Java, the easiest solution depends on what kind of array you have. For String[], String.join is usually the cleanest answer. For non-string values or more complex formatting, streams, Collectors.joining, or StringJoiner give you more control.

Use String.join for String[]

If your array already contains strings, this is the simplest option:

java
1public class JoinStrings {
2    public static void main(String[] args) {
3        String[] words = {"Java", "is", "concise"};
4        String result = String.join(" ", words);
5
6        System.out.println(result); // Java is concise
7    }
8}

This is the direct inverse of many split use cases and is the best default for ordinary string arrays.

Use Streams for Non-String Arrays

If the array contains numbers or other objects, convert each element to text first.

java
1import java.util.Arrays;
2import java.util.stream.Collectors;
3
4public class JoinNumbers {
5    public static void main(String[] args) {
6        Integer[] values = {10, 20, 30};
7
8        String result = Arrays.stream(values)
9                .map(String::valueOf)
10                .collect(Collectors.joining(", "));
11
12        System.out.println(result); // 10, 20, 30
13    }
14}

This is also useful when you want filtering or transformation before joining.

Join Primitive Arrays

Primitive arrays such as int[] need a slightly different approach because they are not arrays of objects.

java
1import java.util.Arrays;
2import java.util.stream.Collectors;
3
4public class JoinPrimitiveArray {
5    public static void main(String[] args) {
6        int[] values = {1, 2, 3, 4};
7
8        String result = Arrays.stream(values)
9                .mapToObj(String::valueOf)
10                .collect(Collectors.joining("-"));
11
12        System.out.println(result); // 1-2-3-4
13    }
14}

That is the clean way to handle primitive numeric arrays without manual loops.

Use StringJoiner for Incremental Construction

If values arrive over time instead of starting in a finished array, StringJoiner is a good fit.

java
1import java.util.StringJoiner;
2
3public class JoinerExample {
4    public static void main(String[] args) {
5        StringJoiner joiner = new StringJoiner(", ");
6        joiner.add("apple");
7        joiner.add("banana");
8        joiner.add("orange");
9
10        System.out.println(joiner.toString()); // apple, banana, orange
11    }
12}

This is useful in loops, builders, and formatting code where you do not want to manage separator placement manually.

Manual StringBuilder Still Has a Place

If you are on very old Java or need highly custom joining logic, a StringBuilder loop still works well.

java
1String[] items = {"a", "b", "c"};
2StringBuilder builder = new StringBuilder();
3
4for (String item : items) {
5    if (builder.length() > 0) {
6        builder.append("|");
7    }
8    builder.append(item);
9}
10
11System.out.println(builder); // a|b|c

This is more verbose than String.join, but it is flexible and explicit.

Watch Out for null Values

Joining becomes less obvious when arrays may contain null. Depending on the API and input, you may get "null" text or a NullPointerException.

With streams, you can normalize the values before joining:

java
1String[] items = {"alpha", null, "gamma"};
2
3String result = Arrays.stream(items)
4        .map(item -> item == null ? "" : item)
5        .collect(Collectors.joining(","));
6
7System.out.println(result); // alpha,,gamma

If null values are possible, decide explicitly whether to skip them, replace them, or fail fast.

Common Pitfalls

The most common mistake is using Arrays.toString(array) and expecting a plain joined string. That method adds square brackets and formatting intended for debugging, not structured output.

Another issue is trying to use String.join directly on non-string arrays such as Integer[] or int[]. Convert elements to strings first.

Some code also manually appends separators at the end and then trims them later. That works, but it is usually less clean than String.join, Collectors.joining, or StringJoiner.

Finally, think about null handling up front. Joining code is simple until unexpected missing values show up.

Summary

  • Use String.join for String[] and other string collections.
  • Use streams plus Collectors.joining for object arrays that need conversion.
  • Use mapToObj for primitive arrays such as int[].
  • Use StringJoiner when values are added incrementally.
  • Avoid Arrays.toString when you need real separator-based joining output.

Course illustration
Course illustration

All Rights Reserved.