Why does the multidimensional array syntax work - java

When we create a 2d array such as int[][] a = new int[2][3] why is the resulting 2d array consist of a two-element array that contains three-element int arrays instead of the other way around. The reason why I'm confused is that when we make an array we do datatype[], so when we do int[2][3] why don't we put three int[2] arrays into an array with three spots (from the [3]).

The way it's implemented in Java is more logical. Consider the array element access expression: a[x][y]. Currently, it could be nicely decomposed to (a[x])[y] which means "we get an x-th element of a, then we get a y-th element of the result". So imagine if new int[2][3] produced an array of three elements, each is a two-element array. Then the x should be in range 0..2 and y should be in range 0..1 which is the opposite of the dimension order used at the array creation point. That would be absolutely confusing.

I guess you have a point with your logic. Eventhough you could also argument, writing int[2][3] means "first index can have 2 different values, second 3", what leads to the same as how it really works.
In the end, this is just a matter of specification and compilerbuilding. And since it is specified this way and not that way, it is implemented and works this way.

Related

Increment sparse matrix

I am currently manipulating a very huge matrix so I had to use CSR format like this : https://en.m.wikipedia.org/wiki/Sparse_matrix
I managed to convert a normal matrix to a CSR matrix with the 3 arrays IA, JA and A like in the Wikipedia page.
However, I am still confused about this format. How can I do if for example I want to increment the element of line n and column m of the CSR matrix? If for example I want to increment the element at the line n and column m by 1, how will the 3 arrays change?
Thank you very much for your help.
Well, I just quickly read through it but IA and JA both are indexing tables, the array actually containing the values is A. If all the non-zero values are positive then incrementing a non-zero value is trivial and will only modify A. However, what you're asking becomes tricky if some elements are negative or if you increment a cell containing a zero. Indeed, you will need to mutate A not just in a single index, but inserting an element potentially in the middle of the array and updating IA consequently. I think this format is simply terrible for the operation you're looking for, it will have linear worst-case complexity in those situations just for updating a single cell.

Converting a Matlab column array into a Java Array: transposition issue

I know the tittle is not really clear so I am going to do my best to explain the situation here.
I have a Matlab array, say: array = [1,2 ; 3,4]. So basically this is a 4x4 matrix.
I have a java class which goals is to convert matlab matrixes into java arrays. This class has two constructors:
MatlabArray( double[] array );
MatlabArray( double[][] array );
And this class has one member to store the array values:
double[][] values
The class is working perfectly fine with matlab matrices ( both sizes > 1 ), matlab singletons ( 1x1 ) and matlab lines ( 1x2, 1x5 etc ...).
But when it comes to column matrices here comes a downfall, basically a line or a column matrix is still a two dimensional array, it's just that one of its dimension is 1.
When the call to the java constructor is made, the one being called end up being:
MatlabArray( double[] array );
This cause the java arrays to becomes a LINE matrix. Say I had the following Matlab matrix say: array = [1;2;3;4], then the converted java array would be array = {1,2,3,4}
Losing the coherence causes later crashes because the indexes used to access values in the different arrays does not match anymore.
Previously we had a workaround ( people knew when this issue was coming, and they were inverting the indexes ). Workaround which of course I got rid of.
I am looking for ideas to solve this issue in a elegant way, I could specify the dimensions in the constructor but I would rather avoid that.
Thanks for your help

C++ and Java array declaration/definition : differences

my question is really simple (which doesn't imply that the answer will be as simple.. :D )
why do arrays in C++ include the size as part of the type and Java's do not?
I know that Java array reference variables are just pointers to arrays on the heap,but so are C++ pointers to arrays,but I need to provide a size even then.
Let's analyze C++ first:
// in C++ :
// an array on the stack:
int array[*constexpr*];
// a bidimensional array on the stack:
int m_array[*constexpr1*][*constexpr2*];
// a multidimensional array on the stack:
int mm_array[*constexpr1*][*constexpr2*][*constexpr3*];
// a dynamic "array" on the heap:
int *array = new int[n];
// a dynamic bidimensional "array" on the heap:
int (*m_array)[*constexpr*] = new int[n][*constexpr*];
// a dynamic multidimensional "array" on the heap:
int (*mm_array)[*constexpr*][*constexpr*] = new int [n][*constexpr1*][*constexpr2*];
n doesn't have to be a compile time constant expression,all the elements are default initialized. Dynamically allocated "arrays" are not of type array,but the new expression yields a pointer to the first element.
So when I create a dynamic array,all dimensions apart the first one,must be constant expressions (otherwise I couldn't declare the pointer to hold their elements). Is it right??
Now to Java.I can only allocate array on the heap,since this is how Java works:
// a dynamic array on the heap:
int[] array = new int[n];
// a dynamic bidimensional array on the heap:
int[][] m_array = new int[n][];
// a dynamic multidimensional array on the heap:
int[][][] mm_array = new int [n][][];
In Java, it doesn't seem to care about array size when defining an array reference variable (it's an error in Java to explicitly provide a size),and so I just need to provide the size for the first dimension when creating the array. This allows me to create jagged array,which I'm not sure I can create in C++ (not arrays of pointers).
can someone explain me how's that? maybe what's happening behind the curtains should make it clear. Thanks.
That's because in Java, all arrays are single-dimensional. A two-dimensional array in Java is merely an array of references to one-dimensional arrays. A three-dimensional array in Java is merely a one-dimensional array of references to arrays of references to arrays of whatever base type you wanted.
Or in C++ speak, an array in Java, if it's not an array of primitive, it's an "array of pointers".
So, for example, this code:
int[][][] arr3D = new int [5][][];
System.out.println(Arrays.deepToString(arr3D));
Would yield the output:
[null, null, null, null, null]
You can decide to initialize one of its elements:
arr3D[2] = new int[3][];
And the output from the same println would now be:
[null, null, [null, null, null], null, null]
Still no ints here... Now we can add:
arr3D[2][2] = new int[7];
And now the result will be:
[null, null, [null, null, [0, 0, 0, 0, 0, 0, 0]], null, null]
So, you can see that this is an "array of pointers".
In C++, when you allocate a multi-dimensional array the way you described, you are allocating a contiguous array which actually holds all the dimensions of the array and is initialized all the way through to the ints. To be able to know whether it's a 10x10x10 array or a 100x10 array, you have to mention the sizes.
Further explanation
In C++, the declaration
int (*mm_array)[5][3];
means "mm_array is a pointer to a 5x3 array of integers". When you assign something to it, you expect that thing to be a pointer to a contiguous block of memory, which is at least big enough to contain 15 integers, or maybe an array of several such 5x3 arrays.
Suppose you didn't mention that "5" and "3".
int (*mm_array)[][]; // This is not a legal declaration in C++
Now, suppose you are handed a pointer to a newly allocated array, and we have statements like:
mm_array[1][1][1] = 2;
Or
mm_array++;
In order to know where to put the number, it needs to know where index 1 of the array is. Element 0 is easy - it's right at the pointer. But where is element 1? It's supposed to be 15 ints after that. But at compile time, you won't know that, because you didn't give the sizes. The same goes for the ++. If it doesn't know that each element of the array is 15 ints, how will it skip that many bytes?
Furthermore, when is it a 3x5 or a 5x3 array? If it needs to go to element mm_array[0][2][1], does it need to skip two rows of five elements, or two rows of three elements?
This is why it needs to know, at compile time, the size of its base array. Since the pointer has no information about sizes in it, and merely points to a contiguous block of integer, that information will need to be known in advance.
In Java, the situation is different. The array itself and its sub-arrays, are all Java objects. Each array is one-dimensional. When you have an expression like
arr3D[0][1][2]
arr3D is known to be a reference to an array. That array has length and type information, and one dimension of references. It can check whether 0 is a valid index, and dereference the 0th element, which is itself a reference to an array.
Which means that now it has type and length information again, and then a single dimension of references. It can check whether 1 is a valid index in that array. If it is, it can go to that element, and dereference it, and get the innermost array.
Since the arrays are not a contiguous block, but rather references to objects, you don't need to know sizes at compile time. Everything is allocated dynamically, and only the third level (in this case) has actual contiguous integers in it - only a single dimension, which does not require advance calculation.
I guess your real question is, why a stack array must have a fixed size at compile time.
Well, for one, that makes it easier to calculate the addresses of following local variables.
Dynamic size for stack array isn't impossible, it's just more complicated, as you would imagine.
C99 does support variable length arrays on stack. Some C++ compilers also support this feature. See also Array size at run time without dynamic allocation is allowed?
I believe this has to do with what code the compiler issues to address the array. For dynamic arrays you have an array of arrays and cells are addressed by redirecting a redirection.
But multidimensional arrays are stored in contiguous memory and the compiler indexes them using a mathematical formula to calculate the cell position based upon each of the array's dimensions.
Therefore the dimensions need to be known (declared) to the compiler (all except the last one).
Correction:
C sometimes has dimension
Java
Sometype some[];
declaration is itself an (declaration of) reference to Object and can be changed (to new instance or array). This may be one reason so in java dimension cannot be given "on the left side". Its near to
Sometype * some
in C (forgive me, array in Java is much more intelligent and safe)
if we think about pass array to C function, formal situation is similar like in Java. Not only we don't have dimension(s), but cannot have.
void func(Sometype arg[])
{
// in C totally unknown (without library / framework / convention etc)
// in Java formally not declared, can be get at runtime
}
In Java, it doesn't seem to care about array size when defining an array reference variable (it's an error in Java to explicitly provide a size),
It is not Java doesn't care about the initial array size when you define an array. The concept of an array in Java is almost totally different from C/C++.
First of all the syntax for creating an array in Java is already different.
The reason why you are still seeing C/C++ look-alike square brackets in Java when declaring arrays is because when Java was implemented, they tried to follow the syntax of C/C++ as much as possible.
From Java docs:
Like declarations for variables of other types, an array declaration has two components: the array's type and the array's name. An array's type is written as type[], where type is the data type of the contained elements; the brackets are special symbols indicating that this variable holds an array. The size of the array is not part of its type (which is why the brackets are empty)
When you declare an array in Java, for e.g.:
int[] array;
You are merely creating an object which Java called it an array (which acts like an array).
The brackets [ ] are merely symbol to indicate this is an Array object. How could you insert numbers into a specific symbol which Java uses it to create an Array Object!!
The brackets looks like what we used in C/C++ array declaration. But Java gives a different meaning to it to the syntax looks like C/C++.
Another description from Java docs:
Brackets are allowed in declarators as a nod to the tradition of C and C++.
Part of your question:
This allows me to create jagged array,which I'm not sure I can create in C++ (not arrays of pointers).
From Java Docs:
In the Java programming language, a multidimensional array is an array whose components are themselves arrays. This is unlike arrays in C or Fortran. A consequence of this is that the rows are allowed to vary in length
If you are interested to find out more on Java Arrays, visit:
here
here
and here
The difference between in arrays in C++ and Java is that Java arrays are references, like all non-primitive Java objects, while C++ arrays are not, like all C++ objects (yes, you hear a lot that C++ arrays are like pointers, but see below).
Declaring an array in C++ allocates memory for the array.
int a[2];
a[0] = 42;
a[1] = 64;
is perfectly legal. However, to allocate memory for the array you must know its size.
Declaring an array in Java does not allocate memory for the array, only for the reference, so if you do:
int[] a;
a[0] = 42;
you'll get a NullPointerException. You first have to construct the array (and also in Java, to construct the array you need to know its size):
int[] a = new int[2];
a[0] = 42;
a[1] = 64;
So what about C++ array being pointers? Well, they are pointers (because you can do pointer arithmetic with them) but they are constant pointers whose value is not actually stored in the program but known at compile time. For this reason the following C++ code will not compile:
int a[2];
int b[2];
a = b;
You're confusing the meaning of some of your C++ arrays:
e.g., your 'm_array' is a pointer to an array of values - see the following compilable C++ example:
int array_of_values[3] = { 1, 2, 3 };
int (*m_array)[3] = &array_of_values;
the equivalent Java is:
int[] array_of_values = {1, 2, 3};
int[] m_array = array_of_values;
similarly, your 'mm_array' is a pointer to an array of arrays:
int array_of_array_of_values[3][2] = { 1, 2, 3, 4, 5, 6 };
int (*mm_array)[3][2] = &array_of_array_of_values;
the equivalent Java is:
int[][] array_of_array_of_values = { {1, 2}, {3, 4}, {5, 6} };
int[][] mm_array = array_of_array_of_values;

difference between 2d array and hashmap

I am relatively new to Java and I just want to make sure I get the basic concepts correctly. So my question is how is hashmap different to 2d array. I will illustrate an example and if someone could possibly correct me if I am wrong that would be great. So
You cannot access/change the 1st array of the 2d array directly in contrast to hashmap. So for example if you have got arr[2][5] the first arr[2] you cannot change it to something else.In other words if we have int arr[2][2] you cannot change it to say arr[Cars][2] whereas with hashmap you can. You cannot even access this at all whereas with hashmap you can. If you have got map Martin, 25 you can possibly make this to Joe, 22 easily.
You can search quite easily in hashmap on the first value. Say if you want to find the age of martin from the previous example you can easily search on Martin and the age 25 will appear.
I have been taught that 2d arrays represent a table. Something like.
arr[2][3]
1 [1 , 2 , 3]
2 [1 , 2 , 3]
But in reality you cannot access/change 1 and 2 outside the [] grid. This should serve only as an imaginary help to illustrate the concept of 2d arrays.
Could you please correct me if I am wrong or make any additional comments on that.
Thank you
A hashmap uses keys and values, not indices. Therefore you can only search for keys, and thus not access any index. Keys need to be unique, you can not have two identical keys, the old key's value will be replaced if you try to reassign something to it. In a hashmap, key can be any object (an index of an array has to be a number). The key kind of works as the index of an array. As said before, the key can be any object, an array's indexes must be int primitives.
It's like comparing apples and oranges.
A 2D array is just a bidimensional grid of objects, an HashMap is a special kind of associative array (called also dictionary or map) which associates generic keys to generic values. The HashMap is not the only one existing, a TreeMap, for example, exists too, which provides roughly the same interface but a totally different implementation.
The other main difference is that an HashMap is made to fulfill a specific requirement which is unnecessary in an array: being able to store sparse keys without wasting too much space while keeping complexity of get and set operation constant.
This can be seen easily:
int[] intMap = new int[10];
HashMap<Integer,Integer> hashIntMap = new HashMap<Integer,Integer>();
Now suppose that you want to insert the pair (500,100):
intMap[500] = 100;
hashIntMap.put(500, 100);
In the first case you will need to have enough room in the array (at least 501 elements) to be able to access cell at index 500. In an HashMap there is no such requirement since elements are stored by using an hash code and bucketed in a lot less cells than the required one.

Merging sorted arrays without using a sort function in Java

I have an assignment question that I need to solve without using a 'sort' commmand. I would appreciate any advice.
QUESTION: Suppose you have two arrays of ints, arr1 and arr2, each containing integers that are sorted in ascending order.
Write a static method named merge that recieves these two arrays a parameters and returns a reference to a new, sorted array of ints that is the result of merging the ints of arr and arr2.
Look into merge sort.
Pseudocode:
1: Set two pointers to beginning of the two arrays.
2: Compare the values from the two arrays at the pointers.
3: Add the smaller value to a new array and move its pointer to the next value in the array.
4: Repeat till both pointers cross the ends of the two arrays.
easy, this is the final step of the merge sort algorithm. make 2 integer variables to keep track of the index for each different input array.
Then loop through as many times as there are elements adding the minimum(or maximum depending on your sort order) out of the 2 first elements in the input arrays. This way on each iteration the smallest possible value is added to the return array. Just make sure to check that your first input array index is still less than the first input array length, if it is not then you know the rest of the elements to add are in the second input array. Increment the index for whichever array you took the element from, and increment your index for the overall array of values then.
If you need extra points or if you are bored: the relatively new Timsort algorithm uses a slightly improved merge function for the case where data is clustered (which is relatively common). This is documented in http://svn.python.org/projects/python/trunk/Objects/listsort.txt - search for "galloping mode". The galloping mode is also used in the Java implementation of timsort.

Categories