Thursday, 14 July 2011

Stringifying Java Arrays

J2SE 5 provided significant new language features that made Java significantly easier to use and more expressive than it had ever been. Although "big" new J2SE 5 features such as enums, generics, and annotations, there was a plethora of new APIs and methods that have made our lives easier ever since. In this post, I briefly look at two of my favorites when dealing with Java arrays: the Arrays.toString(Object[]) method and the Arrays.deepToString(Object[]) method.

The Arrays class has been around since JDK 1.2, but the methods for conveniently and simply converting arrays to a readable String including relevant array content without using Arrays.asList() were added with J2SE 5. Both Arrays.toString(Object[]) and Arrays.deepToString(Object[]) are static methods that act upon the arrays provided to them. The former, Arrays.toString(Object[]), is intended for single-dimension arrays while the latter, Arrays.deepToString(Object[]), is intended for multi-dimensional arrays. As my example later in this post will demonstrate, the multi-dimension deepToString will produce expected results even for single-dimension arrays. The two methods also provide easy and safe null handling, something that I appreciate.

The next code listing is for a simple demonstration class that demonstrates trying to put the contents of various types of Java arrays into a String format. The types of arrays demonstrated are a single dimension array, a double dimensional array representing multi-dimensional arrays of various sizes, and an array that is really just null. The three methods demonstrated for getting a String out of these three types of arrays are (1) simple Object.toString() on each array (implicitly in case of null array to avoid the dreaded NullPointerException), (2) Arrays.toString(Object[]), and (3) Arrays.deepToString(Object[]).
package com.vaani.arraytest;

import java.util.Arrays;
import static java.lang.System.out;

/**
* Simple demonstration of Arrays.toString(Object[]) method and the
* Arrays.deepToString(Object[]) method.
*/
public class Array2String
{
/**
* Demonstrate usage and behavior of Arrays.toString(Object[]).
*/
private static void demonstrateArraysToString()
{
out.println(
"Single Dimension Arrays.toString: "
+ Arrays.toString(prepareSingleDimensionArray()));
out.println(
"Double Dimension Arrays.toString: "
+ Arrays.toString(prepareDoubleDimensionArray()));
out.println(
"Null Array Arrays.toString: "
+ Arrays.toString(prepareNullArray()));
}

/**
* Demonstrate usage and behavior of Arrays.deepToString(Object[]).
*/
private static void demonstrateArraysDeepToString()
{
out.println(
"Single Dimension Arrays.deepToString: "
+ Arrays.deepToString(prepareSingleDimensionArray()));
out.println(
"Double Dimension Arrays.deepToString: "
+ Arrays.deepToString(prepareDoubleDimensionArray()));
out.println(
"Null Array Arrays.deepToString: "
+ Arrays.deepToString(prepareNullArray()));
}

/**
* Demonstrate attempting to get String version of array with simple toString()
* call (not using Arrays class).
*/
private static void demonstrateDirectArrayString()
{
out.println("Single Dimension toString(): " + prepareSingleDimensionArray().toString());
out.println("Double Dimension toString(): " + prepareDoubleDimensionArray());
out.println("Null Array toString(): " + prepareNullArray());
}

/**
* Prepare a single-dimensional array to be used in demonstrations.
*
* @return Single-dimensional array.
*/
private static Object[] prepareSingleDimensionArray()
{
final String[] names = {"Aaron", "Bianca", "Charles", "Denise", "Elmer"};
return names;
}

/**
* Prepare a double-dimension array to be used in demonstrations.
*
* @return Double-dimensional array.
*/
private static Object[] prepareDoubleDimensionArray()
{
final Object[][] namesAndAges = {
{"Aaron", 10}, {"Bianca", 25}, {"Charles", 32}, {"Denise", 29}, {"Elmer", 67}};
return namesAndAges;
}

/**
* Prepare a null array.
*
* @return Array that is really null.
*/
private static Object[] prepareNullArray()
{
return null;
}

/**
* Main executable function for demonstrating Arrays.toString(Object[]) and
* Arrays.deepToString(Object[]) methods.
*/
public static void main(final String[] arguments)
{
out.println("\n\n\nDemonstrating direct array to string using toString():");
demonstrateDirectArrayString();

out.println("\n\n\nDemonstrating Arrays.toString() to get arrays as String:");
demonstrateArraysToString();

out.println("\n\n\nDemonstrating Arrays.deepToString() to get the String:");
demonstrateArraysDeepToString();
}
}


The above code exercises the three mentioned approaches for getting a String out of an array on the three different types of arrays: single dimension, multi dimension, and null array. The output from running this code demonstrates the utility of the different approaches. That output is shown next.

Demonstrating direct array to string using toString():
Single Dimension toString(): [Ljava.lang.String;@3e25a5
Double Dimension toString(): [[Ljava.lang.Object;@19821f
Null Array toString(): null
///////////
Demonstrating Arrays.toString() to get arrays as String:
Single Dimension Arrays.toString: [Aaron, Bianca, Charles, Denise, Elmer]
Double Dimension Arrays.toString: [[Ljava.lang.Object;@addbf1, [Ljava.lang.Object;@42e816, [Ljava.lang.Object;@9304b1, [Ljava.lang.Object;@190d11, [Ljava.lang.Object;@a90653]
Null Array Arrays.toString: null


///////////
Demonstrating Arrays.deepToString() to get the String:
Single Dimension Arrays.deepToString: [Aaron, Bianca, Charles, Denise, Elmer]
Double Dimension Arrays.deepToString: [[Aaron, 10], [Bianca, 25], [Charles, 32], [Denise, 29], [Elmer, 67]]
Null Array Arrays.deepToString: null

The code above and its corresponding output lead to several observations:



  1. Simple Object.toString() on arrays is seldom what we want as it only prints the String representation of the array itself and not of its contents.
  2. Arrays.toString(Object[]) will print a String representation for multi-dimensional arrays, but this representation suffers the same drawbacks as Object.toString() after the first dimension. The first dimension (and only dimension for a single dimension array) gets put into an expected String, but deeper dimensions have the same Object.toString() treatment.
  3. Arrays.deepToString(Object[]), while intended for multi-dimensional arrays, produces the expected results for both single and multi-dimensional arrays.
  4. Both Arrays.toString(Object[]) and Arrays.deepToString(Object[]) handle null array gracefully, simply returning a String "null".

I tend to use Java Collections far more than I use Java arrays. However, when I do need to work with arrays, it is nice to have the many useful features of the java.util.Arrays class. As this post has demonstrated, Arrays.toString(Object[]) and Arrays.deepToString(Object[]) are particularly valuable in obtaining a useful String representation of an array's contents. The java.util.Arrays class provides similar "deep" methods for performing equals and hashCode functionality on multi-dimensional arrays: Arrays.deepEquals and Arrays.deepHashCode.

No comments:

Post a Comment