⌛⌛⌛ N-dimensional array¶
Place your code into a file named NdArray.java in the directory Round7/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.
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
sizeanditeratordescribed below.Inheriting the class will in effect make
NdArraya more or less fully featured Java container container class.NdArrayobjects could e.g. be processed with streams by using the inherited member functionstream().
Constructor
NdArray(Integer firstDimLen, Integer ...furtherDimLens)that receives one or more dimension sizes.The parameters list the sizes of dimensions 1…``N``.
firstDimLenis the size of the first dimension andfurtherDimLenslists 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 offurtherDimLensparameters (size of that array).
Each dimension size must be non-negative (0 is allowed).
If some dimension size is negative, throw a
NegativeArraySizeExceptionexception with a message “Illegal dimension size dimLen.”, wheredimLenis the first negative dimension size among the parameters.
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 = 20.Member function
E get(int... indices)that returns the item at the array location specified byindices.The number of
indicesmust be equal to the number of dimensionsN.If the number of parameters is wrong, throw an
IllegalArgumentExceptionexception with a message “The array has N dimensions but x indices were given.”, whereNis the number of dimensions andxis the number ofindicesparameters.
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."”, whereiis the first illegal index withinindices, anddimanddimLenare the ordinal number and size of the corresponding dimension. The ordinal numbers of the dimensions are 1, …,N.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.
Member function
void set(E item, int... indices)that storesiteminto the array location specified byindices.The
indicesparameters are subject to the same rules as in thegetfunction. 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
Nand the value at indexitells the size of dimension (``i``+1).NdArrayprobably 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 inheritedAbstractCollection<E>does).Iterater the array items in the same order as a typical way of using
Nnested 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 class).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 one-dimensional table.
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.
Testing¶
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.
A+ presents the exercise submission form here.