0

As far as I understand a two-dimensional array in java is an array of arrays. Analogously to the usual array notation I would expect this to mean that

int[][]

is actually

(int[])[]

(An array of int arrays). Thus I would expect the length of the array

int[][] array = new int[2][3]; // (int[2])[3] 

to be 3 (as it would be an array of length 3 of arrays of length 2). It does however appear to be the other way round.

I tried to find an explanation for this, but was unable to. I found many posts explaining how to initialize multidimensional arrays and that they are arrays of arrays but I was unable to find any explanation of why the order of the indices works out this way.

My only theory is that people find it more natural to iterate over the left index first and Java is built in a way such that this operation is more efficient so the developers made this choice very deliberately.

I am thankful for any source confirming this interpretation or any other reasons why it works out this way.


edit: Since there seems to be some confusion as to why anyone would ever believe using the indices the other way round would be a good idea, here is some clarification:

For a type T the expression new T[5] usually yields an array of size 5. The type int[] seems to be a perfectly good type, however Java does not allow me to say new (int[])[5] and instead forces me to initiate this array of arrays using new int[5][]. I was looking for a reason why Java would do that to me (and got one).


One other thing I would like to add with respect to the (very good) answers for anyone thinking like me: In a world where nobody had ever thought about two-dimensional arrays and you were allowed to create arrays of type int[] as you would create any other array, the following might be perfectly legal code.

    int[][] = new (int[])[5];
    int[] firstArray = new int[3];
    int[0] = firstArray;
    int[0][2] = 1; // last element of first array
    int[0][4] = 2; // IndexOutOfBoundsException, trying to access 5th element of firstArray

This would of course be utterly confusing so I am glad that multidimensional arrays get a special treatment.

Corinna
  • 165
  • 7
  • @TimBiegeleisen: Could you explain why you elected to reopen this question? The duplicate answers the specific question as to how the lengths of n-dimensional arrays are calculated. – Makoto Oct 22 '18 at 03:43
  • @Makoto The OP isn't just asking how to calculate the length of an array. There is a misconception about how arrays work in Java, which my answer attempts to clarify. If you can find an exact duplicate, then drop a comment and maybe someone else can reclose. – Tim Biegeleisen Oct 22 '18 at 03:47
  • why you expected that to be length of `3`? – The Scientific Method Oct 22 '18 at 03:52
  • @TimBiegeleisen: In that explanation is precisely the same answer that you're providing. It takes more reading, but it isn't the case that the duplicate is *inappropriate*. – Makoto Oct 22 '18 at 03:55
  • I didn't bother to check given how you phrased your comment. I assume you hadn't read this entire question; perhaps I'm in the wrong for not reading your entire duplicate. – Tim Biegeleisen Oct 22 '18 at 03:56
  • Considering that you still have a close vote...perhaps this could be fixed...? – Makoto Oct 22 '18 at 03:59
  • I don't see which question is the supposed duplicate, but I hope my edit clarified the question. I am more asking about "why" and less about "how". – Corinna Oct 22 '18 at 16:17
  • Searching for multi- instead of two-dimensional arrays I also found this answer: https://stackoverflow.com/a/7913679/2820239 where `arr[i][j][k]` is described as `((arr[i])[j])[k]`, which would imo (and that of another commenter) imply that its length was k. So I think other people might share my confusion. – Corinna Oct 22 '18 at 16:24

3 Answers3

4

An expression like new int[2][5] will create an outer array of length 2, with each element referencing an array of length 5, so a total of 3 arrays are created. This is well-documented in the Java Language Specification, Example 15.10.2-2. Multi-Dimensional Array Creation:

The declaration:

float[][] matrix = new float[3][3];

is equivalent in behavior to:

float[][] matrix = new float[3][];
for (int d = 0; d < matrix.length; d++)
    matrix[d] = new float[3];

It does not mean (int[2])[5], i.e. an array of 5 referencing arrays of 2.

Because of that, the expression to lookup values is evaluated left-to-right, e.g. x[2][5] means (x[2])[5], i.e. in int[][] x variable, lookup x[2], which is an int[], and in that array lookup value at index 5.

int[][] x = new int[9][9];
// z = x[2][5]
int[] y = x[2];
int z = y[5];
Community
  • 1
  • 1
Andreas
  • 154,647
  • 11
  • 152
  • 247
2

You may think of a two dimensional array in Java as an array of arrays. Consider the following general 2D array of numbers:

1 2 3
4 5 6
7 8 9

We could define this array as:

int[][] array = new int[][] {{1,2,3}, {4,5,6}, {7,8,9}};

Or, we could use an empty constructor, and then populate the individual values:

int[][] array = new int[3][3];
array[0][0] = 1;
array[0][1] = 2;
// etc.

But to better understand how 2D arrays in Java work, consider the following approach:

int[][] array = new int[3][];
arr[0] = new int[] {1, 2, 3};
arr[1] = new int[] {4, 5, 6};
arr[2] = new int[] {7, 8, 9};

Hopefully it is clear what a 2D array actually is; it is an array of arrays, so we may visualize this as:

[ ] -> [1, 2, 3]
[ ] -> [4, 5, 6]
[ ] -> [7, 8, 9]

That is, each element in the first index of the array, of size 3, corresponding to the rows, points to another 1D array, corresponding to the columns. Note that in Java a 2D array can be jagged, meaning that we could also have done this:

int[][] array = new int[3][];
arr[0] = new int[] {1, 2, 3, 4, 5};
arr[1] = new int[] {1, 2, 3};
arr[2] = new int[] {7, 7, 7};

To address the concern raised by @Henry in a comment below, that the size of the leftmost portion of the above 2D array is 3 agrees with what we see when we draw it out. Namely, we see a 1D array with 3 buckets, each of which points to another 1D array of some size.

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • All that is true, but does not answer the question why the first index corresponds to the outer array. As the OP says the syntax suggests it would be the inner array. – Henry Oct 22 '18 at 04:24
  • @Henry I disagree that the syntax suggests this. But I do find it confusing, which is why I posted. – Tim Biegeleisen Oct 22 '18 at 04:26
  • Even though it does not directly answer my question, the case where just one dimension is defined is actually a better example than my initial one as to why the order would be confusing so thank you for it! – Corinna Oct 22 '18 at 16:15
2

The reason for this is the importance of array accesses. You have an array of arrays (int[][]). You then retrieve an array from it (int[]). You then retrieve an element from that (int).

There are two ways of doing this. The first is most important:

for (int i = 0; i < matrix.length; i++) {
    int[] row = matrix[i];
    for int j = 0; j < row.length; j++) {
        int element = row[j];
    }
}

It would be absurd to have to use int[] row = matrix[][i]; in the first example, since the convention is to have array[i] represent the first element of array. In this case, the first element of array is a row, not an element.

The same index ordering is applied consistently throughout.


This is also consistent with the fact that you can have a matrix-like object of strange dimensions with an Object[] array. Perhaps one element of that array will be an int[][][] while the next will be an int[]. It would be a bit odd to have to somehow figure out whether to put array[][][][i] or array[][i] when you don't know the dimensionality of subarray i and the subarrays don't even necessarily have a consistent number of dimensions.

Chai T. Rex
  • 2,972
  • 1
  • 15
  • 33
  • The last paragraph is not quite supporting your main point (which is excellent). With a multi-dimensional `Object` array you couldn't put `array[i][j]` without a cast, since `array[i]` is nominally of type `Object`. So even the actual semantics of Java doesn't help here. I think the answer would be stronger without that paragraph. It is worth noting that, say, an `int[][]` array doesn't need to be rectangular; the first-level elements can be arrays of all different lengths. – Ted Hopp Oct 22 '18 at 04:35
  • The idea in the question is that the order of indexing would be reversed, and the outer array would be the last index (*e.g*., `array[][i]`). Regardless of casting, this cannot be done coherently with an incoherent number of dimensions to the array. This goes much further than a nonrectangular array. – Chai T. Rex Oct 22 '18 at 04:37
  • I agree. That is the main point of the first part of your answer. But talking about storing mixed-dimensionality arrays inside an `Object[]` doesn't seem at all relevant to OP's question. The order of indexing has nothing to do with how difficult it would be to cast an element of an `Object[]` to the correct array type. – Ted Hopp Oct 22 '18 at 04:54