1. Overview

In Java applications, it’s often necessary to display data in a table-like format. System.out offers several ways to do this, from simple string concatenation to advanced formatting techniques.

In this tutorial, we’ll explore various methods to format output in a table-like structure using System.out.

2. Using String Concatenation

The simplest way to format output in a table is by using string concatenation. While this method is straightforward, it requires manual adjustment of spaces and alignment:

void usingStringConcatenation() {
    String[] headers = {"ID", "Name", "Age"};
    String[][] data = {
        {"1", "James", "24"},
        {"2", "Sarah", "27"},
        {"3", "Keith", "31"}
    };

    System.out.println(headers[0] + "   " + headers[1] + "   " + headers[2]);

    for (String[] row : data) {
        System.out.println(row[0] + "   " + row[1] + "   " + row[2]);
    }
}

The expected output is:

ID   Name   Age
1   James   24
2   Sarah   27
3   Keith   31

While this approach works, it becomes cumbersome when dealing with dynamic data, as it requires manual adjustment to maintain alignment.

3. Using printf()

The System.out.printf() method provides a more flexible way to format strings. We can specify the width of each column and ensure proper alignment:

void usingPrintf() {
    String[] headers = {"ID", "Name", "Age"};
    String[][] data = {
        {"1", "James", "24"},
        {"2", "Sarah", "27"},
        {"3", "Keith", "31"}
    };

    System.out.printf("%-5s %-10s %-5s%n", headers[0], headers[1], headers[2]);

    for (String[] row : data) {
        System.out.printf("%-5s %-10s %-5s%n", row[0], row[1], row[2]);
    }
}

The expected output will be as follows:

ID    Name       Age  
1     James      24   
2     Sarah      27   
3     Keith      31  

In the printf method, %-5s specifies a left-aligned string with a width of 5 characters. While %-10s specifies a left-aligned string with a width of 10 characters.

This approach is much cleaner and ensures that the columns are aligned regardless of the data’s length.

4. Using String.format()

If we need to store the formatted output in a string instead of printing it directly, we can use String.format(). This method uses the same formatting syntax as printf().

void usingStringFormat() {
    String[] headers = {"ID", "Name", "Age"};
    String[][] data = { 
        {"1", "James", "24"}, 
        {"2", "Sarah", "27"}, 
        {"3", "Keith", "31"} 
    };

    String header = String.format("%-5s %-10s %-5s", headers[0], headers[1], headers[2]);
    System.out.println(header);

    for (String[] row : data) {
        String formattedRow = String.format("%-5s %-10s %-5s", row[0], row[1], row[2]);
        System.out.println(formattedRow);
    }
}

The output is identical to the printf() example. The difference is that String.format() returns a formatted string, which we can use for further processing or logging:

ID    Name       Age  
1     James      24   
2     Sarah      27   
3     Keith      31   

5. Using StringBuilder

When dealing with dynamic or large amounts of data, constructing the table with a StringBuilder can be more efficient. This approach allows us to build the entire output as a single string and print it once:

void usingStringBuilder() {
    String[] headers = {"ID", "Name", "Age"};
    String[][] data = { 
        {"1", "James", "24"}, 
        {"2", "Sarah", "27"}, 
        {"3", "Keith", "31"} 
    };

    StringBuilder table = new StringBuilder();

    table.append(String.format("%-5s %-10s %-5s%n", headers[0], headers[1], headers[2]));

    for (String[] row : data) {
        table.append(String.format("%-5s %-10s %-5s%n", row[0], row[1], row[2]));
    }

    System.out.print(table.toString());
}

Expected Output:

ID    Name       Age  
1     James      24   
2     Sarah      27   
3     Keith      31   

This method is particularly useful when we need to create complex outputs or when performance is a concern, as StringBuilder reduces the overhead of multiple-string concatenation.

6. Using ASCII Table

We can use external libraries like ASCII Table. It is a third-party library that makes it easy to create a nice-looking ASCII table.

To use ASCII Table methods, we need to include its dependency in our project:

<dependency>
    <groupId>de.vandermeer</groupId>
    <artifactId>asciitable</artifactId>
    <version>0.3.2</version>
<dependency>

We can then use its methods to create a table-like structure. Here’s an example using ASCII Table:

void usingAsciiTable() {
    AsciiTable table = new AsciiTable();
    table.addRule();
    table.addRow("ID", "Name", "Age");
    table.addRule();
    table.addRow("1", "James", "24");
    table.addRow("2", "Sarah", "27");
    table.addRow("3", "Keith", "31");
    table.addRule();
    String renderedTable = table.render();
    System.out.println(renderedTable);
}

The expected output will be:

┌──────────────────────────┬─────────────────────────┬─────────────────────────┐
│ID                        │Name                     │Age                      │
├──────────────────────────┼─────────────────────────┼─────────────────────────┤
│1                         │James                    │24                       │
│2                         │Sarah                    │27                       │
│3                         │Keith                    │31                       │
└──────────────────────────┴─────────────────────────┴─────────────────────────┘

7. Conclusion