15

I'm trying to print a table in Java and I was wondering what is the best way to do this?

I've tried printing new lines and using \t to make contents line up but it doesn't work. Is there a method which does this or a better way?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user2704743
  • 1,223
  • 5
  • 15
  • 14

6 Answers6

38

You can use System.out.format(...)

Example:

final Object[][] table = new String[4][];
table[0] = new String[] { "foo", "bar", "baz" };
table[1] = new String[] { "bar2", "foo2", "baz2" };
table[2] = new String[] { "baz3", "bar3", "foo3" };
table[3] = new String[] { "foo4", "bar4", "baz4" };

for (final Object[] row : table) {
    System.out.format("%15s%15s%15s%n", row);
}

Result:

        foo            bar            baz
       bar2           foo2           baz2
       baz3           bar3           foo3
       foo4           bar4           baz4

Or use the following code for left-aligned output:

System.out.format("%-15s%-15s%-15s%n", row);
Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
Luca Mastrostefano
  • 3,201
  • 2
  • 27
  • 34
  • is it possible to do this for an arbitrary number of elements? – corvid Dec 09 '14 at 22:48
  • Sorry corvid, i don't understand your question. Can you explain it better? – Luca Mastrostefano Dec 10 '14 at 21:15
  • Is there a way to left alight this rather than right? – Serguei Fedorov Mar 08 '15 at 20:36
  • Sure, use System.out.format("%-15s%-15s%-15s\n", row); – Luca Mastrostefano Mar 08 '15 at 22:28
  • @corvid - To answer your question 2 years later, the example given already shows how to print an arbitrary number of table elements. The loop is read, "For `row` in `table`" - it goes until it cannot find a next `row`, thus you do not need to know exactly how many elements there are. :) – Kimbluey Jul 12 '16 at 15:43
  • `System.out.format("%-15s%-15s%-15s\n", row);` it expects three strings, but only one (`row`) is provided. Isn't it an error? It certainly gets highlighted as such for me in IDE. – parsecer Oct 03 '20 at 00:07
  • 1
    @Kimbluey what if the array to print contains `500` elements? We can't very well to manually repeat the `%15s` bit `500` times? – parsecer Nov 06 '20 at 03:34
  • @parsecer `row` is an `Object[]`, so it shouldn't be an error – QBrute Aug 28 '22 at 14:27
  • @parsecer I don't really know a good answer to make this work for an arbitrary number of elements in a row, but I would try seeing if you could make the "%15s%15s%15s%n" a variable that you can loop and manipulate, and then try passing in the string variable as the format instead. Don't know if this helps you after so long, but if it does... – Doragon May 24 '23 at 13:07
16

General function to table-format a list of arrays:

public static String formatAsTable(List<List<String>> rows)
{
    int[] maxLengths = new int[rows.get(0).size()];
    for (List<String> row : rows)
    {
        for (int i = 0; i < row.size(); i++)
        {
            maxLengths[i] = Math.max(maxLengths[i], row.get(i).length());
        }
    }

    StringBuilder formatBuilder = new StringBuilder();
    for (int maxLength : maxLengths)
    {
        formatBuilder.append("%-").append(maxLength + 2).append("s");
    }
    String format = formatBuilder.toString();

    StringBuilder result = new StringBuilder();
    for (List<String> row : rows)
    {
        result.append(String.format(format, row.toArray(new String[0]))).append("\n");
    }
    return result.toString();
}

Usage:

List<List<String>> rows = new ArrayList<>();
List<String> headers = Arrays.asList("Database", "Maintainer", "First public release date", "Latest stable version", "Latest release date");
rows.add(headers);
rows.add(Arrays.asList("4D (4th Dimension)", "4D S.A.S.", "1984", "v16.0", "2017-01-10"));
rows.add(Arrays.asList("ADABAS", "Software AG", "1970", "8.1", "2013-06"));
rows.add(Arrays.asList("Adaptive Server Enterprise", "SAP AG", "1987", "16.0", "2015"));
rows.add(Arrays.asList("Apache Derby", "Apache", "2004", "10.14.1.0", "2017-10-22"));

System.out.println(formatAsTable(rows));

The result:

Database                    Maintainer   First public release date  Latest stable version  Latest release date  
4D (4th Dimension)          4D S.A.S.    1984                       v16.0                  2017-01-10           
ADABAS                      Software AG  1970                       8.1                    2013-06              
Adaptive Server Enterprise  SAP AG       1987                       16.0                   2015                 
Apache Derby                Apache       2004                       10.14.1.0              2017-10-22    
Vadim Zverev
  • 468
  • 6
  • 14
5

This is one way to do it:

public class StoreItem {

    private String itemName;
    private double price;
    private int quantity;


    public StoreItem(String itemName, double price, int quantity) {
        this.setItemName(itemName);
        this.setPrice(price);
        this.setQuantity(quantity);
    }


    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }


    public static void printInvoiceHeader() {
        System.out.println(String.format("%30s %25s %10s %25s %10s", "Item", "|", "Price($)", "|", "Qty"));
        System.out.println(String.format("%s", "----------------------------------------------------------------------------------------------------------------"));
    }
    public void printInvoice() {
        System.out.println(String.format("%30s %25s %10.2f %25s %10s", this.getItemName(), "|", this.getPrice(), "|", this.getQuantity()));
    }

    public static List<StoreItem> buildInvoice() {
        List<StoreItem> itemList = new ArrayList<>();
        itemList.add(new StoreItem("Nestle Decaff Coffee", 759.99, 2));
        itemList.add(new StoreItem("Brown's Soft Tissue Paper", 15.80, 2));
        itemList.add(new StoreItem("LG 500Mb External Drive", 700.00, 2));
        return itemList;
    }

    public static void main (String[] args) {

        StoreItem.printInvoiceHeader();
        StoreItem.buildInvoice().forEach(StoreItem::printInvoice);
     }
}

Output:

enter image description here

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
Ojonugwa Jude Ochalifu
  • 26,627
  • 26
  • 120
  • 132
1

Write a function which pads a string to your desired column-length with spaces. This can be a static helper, and you can create a class StrUtils or similar to hold it.

(There may also be Apache or other libraries with String helpers/utils to do this for you.)

Long-term, if you're outputting tabular data you could consider exporting CSV (for Excel etc) or XML. But these are for typical long-term business requirements, not just a quick to-screen output.

Thomas W
  • 13,940
  • 4
  • 58
  • 76
1

I think using J-Text-Utils to output the table for you would be a convenient way. Through this small library, you do not need to reinvent the wheel. You just input your data and it will take care of formatting for you.

This is an example from their Google Code site:

String[] columnNames = {
"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};

Object[][] data = {
{"Kathy", "Smith",
"Snowboarding", new Integer(5), new Boolean(false)},
{"John", "Doe",
"Rowing", new Integer(3), new Boolean(true)},
{"Sue", "Black",
"Knitting", new Integer(2), new Boolean(false)},
{"Jane", "White",
"Speed reading", new Integer(20), new Boolean(true)}, {"Joe", "Brown",
"Pool", new Integer(10), new Boolean(false)}
};

TextTable tt = new TextTable(columnNames, data);
// this adds the numbering on the left
tt.setAddRowNumbering(true);
// sort by the first column
tt.setSort(0);
tt.printTable();

The Output:

Output

Renis1235
  • 4,116
  • 3
  • 15
  • 27
0

Library for printing Java objects as Markdown / CSV / HTML table using reflection: https://github.com/mjfryc/mjaron-etudes-java

dependencies {
    implementation 'io.github.mjfryc:mjaron-etudes-java:0.2.1'
}
Cat[] cats = {cat0, cat1};
Table.render(cats, Cat.class).markdown().to(System.out).run();

Sample Markdown output:

| name | legsCount | lazy  | topSpeed |
|------|-----------|-------|----------|
| John | 4         | true  | 35.24    |
| Bob  | 5         | false | 75.0     |
Michał Jaroń
  • 469
  • 4
  • 11