2. Multi-dimensional Arrays



1. Introduction

In the previous lecture, we saw that array structures can be defined over any class of object instances, i.e. these are not restricted to the basic primitive types.

In this lecture we consider a further development of arrays - multi-dimensional array structures.

The form of arrays encountered, so far, has been 1-dimensional. In other words, the declaration of a 10 element array of integers, is realised by


int [] TenIntegerArray = new int[10]

This results in the allocation of 10 locations indexed from 0 through 9, thus:



Figure 2.1: Allocation of Memory in 1-dimensional 10 element Array

In 1-dimensional arrays, any individual element within the array can be referred to simply by specifying its offset index, e.g. the element with index 4 (the fifth location since the first item is indexed by 0) of TenIntegerArray is TenIntegerArray[4] as shown in Figure 2.1.

While 1-dimensional array structures (whether constrained or unconstrained) suffice to model data representations in a number of applications, there are many cases where it is more natural to think of specific items of data in some ordered collection of data as being referenced by 2,3 or more indices.

Here is a selection of example situations:

Of course, in principle, one could represent such structures by using an appropriate 1-dimensional array within a suitable Class definition, among the methods of which would be mechanisms for accessing a specific index (within the 1-dimensional form) that corresponded to a given row and column of a table, e.g. in the map example of Figure 2.2 such a method would return the value 25 when its parameters were instantiated to A and C.

In some programming languages, e.g. BASIC, it may be necessary to mimic the structure of a multi-dimensional array by devising such indexing mechanisms to map between the `natural' 2,3, etc dimensional structure in which a design solution is developed, and the `linear' 1-dimensional structure of a simple array.

While this is straightforward, in an algorithmic sense, it has a number of disadvantages:

  1. Building multi-dimensional structures by mapping between single dimensional forms can lead to very opaque code: hence there are greater chances of errors.
  2. This approach is rather counter-thematic to a number of accepted principles of good programming practice: in effect the designer is faced with addressing problems of data representation at a very low-level; modern high-level languages recognise that such concerns should be the responsibility of the compiler system for a given language, not a matter for users of the language.


2. Multi-dimensional Array Declarations in Java

Java provides the capability to declare arrays having 2,3,4 ... dimensions using a syntax that is similar in style to that for declaring arrays of a single dimension:

Thus if we wished to declare an array corresponding to a table of 5 rows and 4 columns, each entry of which was an integer value, we could do this by:


int [] [] FiveByFour = new int [5] [4];

This declaration can be interpreted with the array laid out as:



Figure 2.3: 2-dimensional Array (5 by 4); Indexing Row 3 and Column 1

N.B. the usage `interpreted': in terms of the actual physical storage allocation in memory the elements would be stored in 20 consecutive locations: the Java compiler system ensures that references to, say FiveByFour[3][1], would access the 14th of these.

For this lecture we will consider examples involving constrained multi-dimensional arrays, deferring the variations involving unconstrained types until later, i.e. each dimension will have its bounds set when declared.

Consider the example declaration


int [] [] FiveByFour = new int [5] [4];

In general (for a constrained array) this would look like:


< Type>  [] [] [] ...  < NameofArray> = new < Type> [LEN1] [LEN2] [LEN3] ...;

[Important Note: The characters . . . are NOT part of the syntax in the declaration. They are used to indicate that there is no set limit on the number of dimensions allowed; of course the number of bounds that are specified (i.e. the [LENk] parts) must match the number of dimensions specified, e.g. a declaration of the form


int[][] TooFew =new int[5];
will cause a compile-time error. It is valid, however, to use


int[][] NotTooFew =new int[5][];
]

Returning to the examples presented previously, suitable declarations for these would be,