Place your code into a file named NdArray.java in the directory Round8/ndarray. Remember to
pull task material from student_template_project.
In this task you should implement a fixed N-dimensional array as a generic container class
NdArray<E>. The idea is that e.g. an NdArray objecd created as
new NdArray<String>(2, 5, 4) would represent a 3-dimensional String array whose dimensions
have sizes 2, 5 and 4. To be more precise, the first dimension size would be 2, the second 5 and
third 4. In similar manner new NdArray<Double>(3, 3, 3, 3, 3) would create a 5-dimensional
Double array whose all 5 dimensions have size 3.
new NdArray<String>(2, 5, 4)
new NdArray<Double>(3, 3, 3, 3, 3)
The word “fixed” used in the beginning means that the parameters given to the constructor fix the
number and sizes of the array dimensions; they cannot be changed later.
The generic class NdArray<E> should have the following public features:
Inherits the abstract class AbstractCollection<E> from the Java class library.
This requires us to implement the member functions size and iterator described below.
Inheriting the class will in effect make NdArray a more or less fully featured Java
container container class. NdArray objects could e.g. be processed with streams by using
the inherited member function stream().
Constructor NdArray(Integer firstDimLen, Integer ...furtherDimLens) that receives one or more
NdArray(Integer firstDimLen, Integer ...furtherDimLens)
The parameters list the sizes of dimensions 1…``N``.
firstDimLen is the size of the first dimension and furtherDimLens lists the
sizes of dimensions 2…``N`` (if there is more than one dimension).
The first dimension size is received separately in order to force the constructor to
receive at least one parameter.
Therefore the overall number of dimensions N = number of parameters = 1 + number of
furtherDimLens parameters (size of that array).
Each dimension size must be non-negative (0 is allowed).
If some dimension size is negative, throw a NegativeArraySizeException exception with a
message “Illegal dimension size dimLen.”, where dimLen is the first negative
dimension size among the parameters.
Illegal dimension size dimLen.
Member function int size() that returns the overall size of the array (multiplication of its
dimension sizes). E.g. a 3-dimensional array with dimension sizes 2, 5 and 4 has size 2 · 5 · 4 =
Member function E get(int... indices) that returns the item at the array location specified
E get(int... indices)
The number of indices must be equal to the number of dimensions N.
If the number of parameters is wrong, throw an IllegalArgumentException exception with a
message “The array has N dimensions but x indices were given.”, where N is the number
of dimensions and x is the number of indices parameters.
The array has N dimensions but x indices were given.
Each index must be legal, that is, in the interval 0…size of the corresponding dimension - 1.
If any dimension is given an illegal index, throw an``IndexOutOfBoundsException`` exception
with a message “Illegal index i for dimension dim of length dimLen."”, where i is
the first illegal index within indices, and dim and dimLen are the ordinal number
and size of the corresponding dimension. The ordinal numbers of the dimensions are 1, …,
Illegal index i for dimension dim of length dimLen."
E.g. if we have a 3-dimensional array with dimension sizes 2, 5 and 4, the call
get(i, j, k) is legal if and only if 0 ≤ i < 2, 0 ≤ j < 5 and 0 ≤ k < 4.
get(i, j, k)
Member function void set(E item, int... indices) that stores item into the array location
specified by indices.
void set(E item, int... indices)
The indices parameters are subject to the same rules as in the get function. E.g. the
same exceptions are thrown in case of wrong number of indices or an illegal index.
member function int getDimensions() that returns an array containing the dimension sizes.
The returned array has size N and the value at index i tells the size of dimension
NdArray probably maintains this kind of an array internally in order to know its dimension
sizes. But note: do not return this kind of internal array directly! Create and return a new
array because otherwise the function caller could corrupt internal data by modifying the array.
Implements the interface Iterable<E> (because the inherited AbstractCollection<E> does).
Iterater the array items in the same order as a typical way of using N nested loops where
the outermost loop iterates the first dimension, the loop directly inside it iterates the
second dimension, and so on.
Define a suitable iterator class that implements Iterator<E> (e.g. as a private inner
If you follow (and it is a good idea) the advice given below, the iterator can be very
simple: it would suffice to maintain only information about the current iterator index in a
Implement a member function Iterator<E> iterator() that creates and returns an object of
the above described iterator class.
Advice: one relatively simple approach to implement an N-dimensional array is to store the
items into a one-dimensional array. The main challenge is then how to compute a mapping from N
indices to an index of the internal one-dimensional array. The basic principle is described e.g.
in this article
(follow the “row-major” order described first in the article, as that makes iteration trivial). I
do not recommend you to try to implement a “truly” multidimensional solution; it would make the
task much more complicated.
You may test your implementation by using the test program given in the file NdArrayTest.java
and the example output given in the files output1.txt, output2.txt, output3.txt and
output4.txt. Place these files to the same directory with your code, compile the test program
e.g. as javac *.java, and run the tests as java NdArrayTest 1, java NdArrayTest 2,
java NdArrayTest 3 and java NdArrayTest 4. The expected outputs of these tests are given in
the files output1.txt, output2.txt, output3.txt and output4.txt.
java NdArrayTest 1
java NdArrayTest 2
java NdArrayTest 3
java NdArrayTest 4
A+ presents the exercise submission form here.