1. Overview

In Kotlin, working with arrays is a common task, and printing all elements in one single line is a straightforward yet essential operation.

In this tutorial, we’ll explore efficient ways to achieve this goal, emphasizing readability and conciseness in Kotlin code.

2. Introduction to the Problem

We know we can directly print a list using the println() function to output the list element in one line between ‘[‘ and ‘]‘, for example:

println(listOf("A", "B", "C", "D", "E", "F"))
// output: [A, B, C, D, E, F]

However, if we apply the println() function to an array, Kotlin won’t print the array’s elements. Instead, the array type and the object’s hashcode appear in the output:

val myArray = arrayOf("A", "B", "C", "D", "E", "F")
println(myArray)
// output: [Ljava.lang.String;@fdefd3f

Iterating through the array elements and calling println() on each element allows us to print all elements in the output. However, the drawback is that the output displays each element on a separate line. For instance, we’ll get the following output if we call println() in a forEach:

myArray.forEach { println(it) }
/* output:
A
B
C
D
E
F
*/

In this tutorial, we’ll explore various approaches to printing all array elements to a single line in the comma-separated format.

Sometimes, the element values may contain commas. Therefore, we’ll take the following array as another input example to show how to separate the elements properly in the output:

val arrayWithComma = arrayOf("A", "B, C", "D, E", "F")

As usual, we’ll employ unit tests to verify if each approach produces the expected output.

So next, let’s make some preparations to verify the output of println().

3. Verifying the Output Using Unit Tests

Verifying println()‘s output is not as easy as examining variable values. But it’s not a challenge for us either. Let’s first have a look at Kotlin’s println() function’s implementation:

@kotlin.internal.InlineOnly
public actual inline fun println(message: Any?) {
    System.out.println(message)
}

As the code shows, println() invokes Java’s System.out.println() internally. Therefore, we can borrow the approach to unit testing Java’s System.out.println(). The basic idea is to replace the standard output stream with our own ByteArrayOutputStream so that we can capture and verify the output:

val stdOut = System.out
val myOutput = ByteArrayOutputStream()

@BeforeEach
fun setup() {
    System.setOut(PrintStream(myOutput))
}

@AfterEach
fun restore() {
    System.setOut(stdOut)
}

Let’s create a simple test to see if this approach works:

val newLine = System.lineSeparator()

println("Hello, world")
assertEquals("Hello, world$newLine", myOutput.toString())

myOutput.reset()

println("Kotlin rocks")
assertEquals("Kotlin rocks$newLine", myOutput.toString())

As the example above shows, we can reset() our output stream to check outputs produced by new println() calls.

Next, let’s print the array’s elements in one single line.

4. Converting the String Array to a List

We’ve seen println() can print a list of strings in one single line. Therefore, we can convert our array to a list and pass the list to println(). This could be the most straightforward solution:

println(myArray.asList())
assertEquals("[A, B, C, D, E, F]$newLine", myOutput.toString())

Next, let’s look at our arrayWithComma variable. This array contains “B, C” and “D, E” two elements. If we use this approach, we cannot distinguish elements in the output:

myOutput.reset()

println(arrayWithComma.asList())
// we cannot customize the output format
assertEquals("[A, B, C, D, E, F]$newLine", myOutput.toString())

Therefore, since we cannot customize the format while outputting an element, the output might be confusing if some elements contain a comma.

5. Using print() in forEach

The println() function always adds a newline character at the end of the output. However, the print() function doesn’t.

So, we can use print() in a forEach function to output each element during iteration. Of course, we need to check whether an element is the last one to decide to append a separator or the ending newline character:

myArray.forEachIndexed { idx, e ->
    print(if (idx == myArray.lastIndex) "$e$newLine" else "$e, ")
}
assertEquals("A, B, C, D, E, F$newLine", myOutput.toString())

Next, let’s take arrayWithComma as the input and see how to print each element clearly in the output:

myOutput.reset()

arrayWithComma.forEachIndexed { idx, e ->
    print(if (idx == arrayWithComma.lastIndex) """"$e"$newLine""" else """"$e", """)
}
assertEquals(""""A", "B, C", "D, E", "F"$newLine""", myOutput.toString())

As the test above shows, we enclose each element in quotation marks in the output to present array elements clearly.

It’s worth mentioning that we used Kotlin’s raw string to avoid escapes.

6. Using the joinToString() Function

Alternatively, we can utilize Array‘s joinToString() extension function to first concatenate all elements as a comma-separated string and then pass the string to println():

println(myArray.joinToString { it })
assertEquals("A, B, C, D, E, F$newLine", myOutput.toString())

As we have complete control of the element output format in the joinToString()’s lambda expression, quoting each element in the output is an easy task:

myOutput.reset()

println(arrayWithComma.joinToString { """"$it"""" })
assertEquals(""""A", "B, C", "D, E", "F"$newLine""", myOutput.toString())

7. Conclusion

In this article, we’ve explored different ways to print all elements of a string array in a single line in Kotlin. Additionally, we discussed how to unit test println()‘s output through examples.

As always, the complete source code for the examples is available over on GitHub.

Comments are closed on this article!