A Java class that prints a matrix
Your two print methods are odd in the sense that they are inconsistent with how you present them. A 'classic' matrix consists of primitive arrays (like int[][]), and not nested containers (like ArrayList&lt;ArrayList&lt;T&gt;&gt;). I can understand why you have one and also the other, but the mix of them is bizarre, ArrayList&lt;T[]&gt;. Remove the second print method.

Let's go through some other items first though. Let's narrow the ArrayList down to the interface level, just List. There is no reason to constrain the method to the concrete implementation because that severely restricts the applicability. I would actually go further and constrain it to Iterable. This produces the signature:

public static &lt;T, R extends Iterable&lt;T&gt;, M extends Iterable&lt;R&gt;&gt; void printMatrix(M matrix) {
    ....
}


What am I saying there? I am saying that the Matrix can consist of any combination of values that may have an Iterator. The mnemonics I use there are that:


T is the type of the cell data
R is the type of each row (which can be anything that is of type Iterable&lt;T&gt;)
M is the combined Matrix, which can be any Iterable of &lt;R&gt; (i.e. it's a collection of rows)


This is a generic method. You can throw pretty much anything at it from any collection structure.

An implementation of the method would look something like:

public static &lt;T, R extends Iterable&lt;T&gt;, M extends Iterable&lt;R&gt;&gt; void printMatrix(M matrix) {
    int size = -1;
    for (R row : matrix) {
        int s = 0;
        for (@SuppressWarnings("unused") T value : row) {
            s++;
        }
        if (size &lt; 0) {
            size = s;
        } else if (size != s) {
            System.err.println("This is not a matrix.");
            return;
        }
    }

    StringBuilder sb = new StringBuilder();
    for (R row : matrix) {
        sb.setLength(0);
        for (T value : row) {
            sb.append(value).append('\t');
        }
        if (sb.length() &gt; 0) {
            sb.setLength(sb.length()-1);
        }
        System.out.println(sb);
    }
}


and this could be used, for example, like:

public static void main(String[] args) {
    List&lt;Collection&lt;Object&gt;&gt; data = new ArrayList&lt;&gt;();
    data.add(System.getProperties().keySet());
    data.add(System.getProperties().values());
    printMatrix(data);
}


You should note a few things here:


The only reference to any concrete class here is the new ArrayList&lt;&gt;() in the main method. Everything else is treated at the lowest usable interface level (Collections, Lists, Iterables).
I use StringBuilder to build things 1 line at a time. This improves performance because each print is expensive, so you do fewer prints.
Java8 has a better way of counting the members, and also joining the Strings with the \t character:

for (R row : matrix) {
    long s = StreamSupport.stream(row.spliterator(), false).count();
    if (size &lt; 0) {
        size = s;
    } else if (size != s) {
        System.err.println("This is not a matrix.");
        return;
    }
}

for (R row : matrix) {
    StringJoiner sj = new StringJoiner("\t");
    row.forEach(v -&gt; sj.add(String.valueOf(v)));
    System.out.println(sj);
}

There is no need for the array-of-Integer to count the number of values in each line.
By putting the complexity of the generic types in the static method generics declaration area, the actual parameter has the simple type M.