Changing the number of dimensions an Java array has - java

Is there a way of changing the number of dimensions an array has, i.e making this
int[][] i = new int[3][3];
but using it like this
getArray(i); //where getArray only accepts one dimensional arrays
?

You cannot change the number of dimensions in a Java array or array type.
But you can make use of the fact that a Java array is an object ... and subtyping .. and declare a getArray method like this:
Object getArray(Object[], ...) { .... }
You can call this method on a int[][] instance, but a runtime typecast is needed to cast the result to an int[].
For example:
Object getArray(Object[] array, int i) { return array[i]; }
int[][] big = new int[3][3];
int[] slice = (int[]) getArray(big, 0);
On the other hand, if you are really asking about how to flatten a multi-dimensional array into a 1-D array, the getArray method needs to allocate a new array, fill it from the original and return it.
Note you would be returning a brand new array that is unconnected to the original one. And copying an N x N .... x N array is expensive.
For more details: Flatten nested arrays in java

Java is statically-typed language. This means that you cannot change a variable's type at runtime. But in this particular case you can simply use the following invocation:
getArray(i[2]); // put anything between 0 and (outerArrayLength-1) instead of 2 here

Related

Why is declaring an empty array of non-empty array(s) legal in Java?

Curious why declaring an empty array of non-emtpy array(s) is legal in Java:
int[][] array = new int[0][1];
System.out.println(array[][0]); //won't compile.
System.out.println(array[0][0]) //triggers an out of bounds exception.
P.S. I have read the related question on zero-size arrays: Why does Java allow arrays of size 0?
Is this for the same reason?
An int[][] array is an array whose elements are int[] (i.e. its elements are arrays of int).
Just like you are allowed to define an empty array of int elements:
int[] empty = new int[0];
or an empty array of String elements:
String[] empty = new String[0];
You are also allowed to define an empty array of int[1] elements:
int[][] empty = new int[0][1];
Perhaps it's the syntax that is somewhat confusing here.
If it was
int[][] empty = new (int[1])[0]
it would be clearer that you are defining an empty array whose element type is int[1].
However, since the number in the first square brackets represents the number of elements in the outer array, new int[1][0] does not represent an empty array, but an array of a single element (whose single element is an empty int array).
It is legal to define empty arrays in general, no matter what it contains. Thus, it is also legal to have an empty array containing non empty arrays.
Mathematically (group theory) speaking, empty arrays are not only legal, but necessary, since they represent the zero (or neutral) element of array concatenation operation. This also makes it useful for programming (see the example below).
In your example you basically probe, if it is ok to access elements of an empty array. This is of course not legal, since there are none. However you can do:
int[][] array = new int[0][1];
System.out.println(array.length);
With reference to my own example above, a more useful case is:
int[][] array1 = new int[1][1];
int[][] array2 = new int[0][1];
array1[0][0] = 1;
int [][] concat = Stream
.concat(Arrays.stream(array1), Arrays.stream(array2))
.toArray(int[][]::new);
System.out.println(Arrays.deepToString(concat));
Thus empty arrays allow to for "good" code, without ifs to exclude, illegal cases, which actually are totally fine.
as per your declaration:
int[][] array = new int[0][1];
you have declared 2D array where length of the array is 0
it means it will not be able to contain any element thats why
System.out.println(array[0][0]). array[0][0] is out of bound index error
An array dimension of zero means the array has zero elements. Hence there is no element at index 0 (zero).
When you declare a two-dimensional array in Java, the first array dimension is mandatory.
Refer to chapter 10 of the Java Language Specification.

How do I add arrays to an Arraylist of Arrays (Arraylist<Integer[]>)

I want to save the steps pf my player-character in a Sokoban-game.
So at first i want to fill an Array of int x and y, called "pos" with the actual position of the character.
And than i want to add this array to an ArrayList of Arrays, called "moves".
Array for one player-position:
int[] pos = new int [2];
ArrayList for all steps, the player made in the level:
Arraylist<Integer[]> moves = new ArrayList<>();
"int[]" makes an error, if placed inside the pointy brackets at the ArrayList.
How do i add the Array pos to the ArrayList moves?
This works completely fine with int[]. However int[] != Integer[], Use same in both places.
int[] pos = new int[2];
ArrayList<int[]> arrayList = new ArrayList<>();
pos[0] = 1;
pos[1] = 2;
arrayList.add(pos);
System.out.println(arrayList.get(0)[0]+ " "+ arrayList.get(0)[1]);
int and Integer are two different things (I struggled with this as well when I first learned Java a long time ago.
int is a so-called primitive datatype, which means it is not an object. Integer is a wrapper class, basically a class whose only purpose is to contain an
int so that it can be handled as an object. Since Java 5, there is "autoboxing", which means you can assign int values to Integer variables and vice versa, and the compiler will handle it silently. This tends to muddle the difference, but it still is there and important - such as in this case.
So if you want to store instances of int[] in an ArrayList, you need an ArrayList<int[]>, not an ArrayList<Integer[]>.
However, it is impossible to have an ArrayList<int> because ArrayList can only store Objects (the generic types exist only for the compiler), not primitives.
Oh yes, and to add an element to the list, use
Arraylist<int[]> moves = new ArrayList<>();
arrayList.add(pos);
You could have found this in the API doc for ArrayList - you should really learn to use the API doc, you will need it all the time to answer questions such as this.
You can also make class (for example Pos) and make x and y as attributes and make constructor. The you can make the type of arraylist is Pos
ArrayList arrayList = new ArrayList<>();
arrayList.add(new Pos(3,2));

Remove empty dimension from multi-dimensional array

I have this type of array float[1][1][54][54]. If it possible to cast this array to float[54][54]? Maybe it`s possible to remove two first empty dimensions?
You can't cast it, but you can just assign the inner array to a new variable:
float[][][][] arr1 = new float[1][1][54][54];
float[][] arr2 = arr1[0][0];
Note that although they're separate variables, they actually share a reference to the same inner array, so they can't be modified separately.

Why java does not autobox int[] to Integer[]

When I do the following,
arrayList1 - contains one element and it is an int[].
arrayList2 - not compiling (Error : The constructor ArrayList<Integer>(List<int[]>) is undefined)
arrayList3 - contains 7 elements and they are Integer objects
Here's the code:
int[] intArray = new int[]{2,3,4,5,6,7,8};
ArrayList arrayList1 = new ArrayList(Arrays.asList(intArray));
ArrayList<Integer> arrayList2 = new ArrayList<Integer>(Arrays.asList(intArray));
Integer[] integerArray = new Integer[]{2,3,4,5,6,7,8};
ArrayList<Integer> arrayList3 = new ArrayList<Integer>(Arrays.asList(integerArray));
Question :
Why doesn't the compiler auto-box the elements in the int[] to Integer and create an ArrayList<Integer>? What is the reason behind this? Is that my stupidity or some other reason?
The difference is int[] is itself an Object, whereas Integer[] is an array of references to Integer object.
Arrays.asList(T...) method takes variable arguments of some type T with no upper bounds. The erasure of that method is Arrays.asList(Object...). That means it will take variable number of arguments of any type that extends from Object.
Since int is not an Object, but a primitive type, so it can't be passed as individual element of T[], whereas int[] is an Object itself, it will go as first element of the T[] array (T... internally is a T[] only). However, Integer[] will be passed as T[], with each reference in Integer[] passed as different argument to T[].
And even if you would argue that compiler should have done the conversion from each element of int[] array to Integer, well that would be too much work for the compiler. First it would need to take each array element, and box it to Integer, then it would need to internally create an Integer[] from those elements. That is really too much. It already has a direct conversion from int[] to Object, which it follows. Although I have always wished Java allowed implicit conversion from int[] to Integer[], that would have made life simpler while working with generics, but again, that's how the language is designed.
Take a simple example:
Object[] array = new Integer[10]; // this is valid conversion
Object[] array2 = new int[10]; // this is not
Object obj = new int[10]; // this is again a valid conversion
So, in your code Arrays.asList(intArray) returns a ArrayList<int[]> and not ArrayList<Integer>. You can't pass it to the ArrayList<Integer>() constructor.
Related:
int[] and Integer[]: What is the difference?
An int[] is not the same as an Integer[].
An array has as associated Class object. The class object for an array of primitive ints is [I. The class object for an array of Integer is [Ljava/lang/Integer.
An array is itself an object, so converting between two objects of the same type is an identity conversion. Converting between two different typed objects isn't - and int[] and Integer[] are definitely different, as evidenced by the bytecode above.
Lastly, bear in mind that autoboxing would only really apply if there was an associated boxing conversion.
Technically it is possible to do it of course. However autoboxing/unboxing of primitive type array to wrapper type array is more than what you expect.
First look into the auto-boxing/unboxing of Java: What it does is simply a syntax sugar to save you typing the primitive wrapper code. e.g.
Integer i = 10;
Compiler knows that it is expecting an Integer, but int present instead. Therefore what the compiler doing is translating your code to:
Integer i = Integer.valueOf(10);
It does similar thing for unboxing: when in situation that it expects int but Integer is present, compiler replace it with varName.intValue()
Back to array. There are two problems we can forsee:
The first problem is, there is no straight-forward way to transform from an int array to an Integer array. You may argue that the compiler can transform
int[] intArray = ....;
Integer[] wrapperArray = intArray ;
to
Integer[] wrapperArray = new Integer[intArray.size()];
for (int i = 0; i < intArray.size(); i++) {
wrapperArray[i] = Integer.valueOf(intArray[i]);
}
but that seems too much for a syntax sugar.
The second big problem is, when you are passing it as a parameter to a method, if autoboxing/unboxing happens for array, instead of reference of original array is passed, you are now passing the reference of a copy of the original array. In case you are changing the content of array in your method, the original array will not be affected. That can bring you lots of surprises.
e.g.
void foo(Integer[] arr) {
arr[0] = 0;
}
// invoking foo in some code:
int[] intArr = new int[]{9,8,7,6};
foo(intArr);
// intArr[0] will still be 9, instead of 0
Because int[] and Integer[] both are objects. First will hold primitive int values, which are not of type Object while second will store references of Integer objects, which are of type Object.
arrayList1 is really a List of size one.
http://ideone.com/w0b1vY
arrayList1.size() = 1
arrayList3.size() = 7
The int[] is being cast to a single Object. That Object cannot be cast to Integer.

How to copy a array into another array that already has data in it?

How would I copy an array say
float arraytobecopied[] = {1.20,2.50,3.60};
to another array that has data in it already say
float newarray[] = {5.20,6.30,4.20};
I want to add the the arraytobecopied to the end of the new array and keep the values in the array. also as a side note this would be an on going process adding to the end of the array every time.
Should i just use a for loop? or is there a better way.
(Can't use Array) already tried:(
This question has been asked here before, You can see this page for the answer. How can I concatenate two arrays in Java?
Use System.arraycopy
public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)
You can't increase the size of the original array. But you could create a new array, copy both source arrays into it, and assign your reference variable to it.
For example, here's a sketch of a simple implementation. (An alternative is to use System.arraycopy().)
float[] newerArray = new float[ newarray.length + arraytobecopied.length ];
for ( int i = 0; i < newarray.length; ++i ) {
newerArray[i] = newarray[i];
}
for ( int i = 0; i < arraytobecopied.length; ++i ) {
newerArray[ newarray.length + i ] = arraytobecopied[i];
}
newarray = newerArray; // Point the reference at the new array
Alternatively, you could use a java.util.ArrayList, which automatically handles growing the internal array. Its toArray() methods make it easy to convert the list to an array when required.
The easiest approach from a programming perspective is to use a List<Float> (if you can use Float values instead of float) or a third-party library such as Apache Commons Collections or Trove that provides dynamic arrays of primitives.
If you need to use a simple array of primitives (and not a wrapper class), you can use a couple of methods in the java.util.Arrays and java.lang.System classes to help:
int len1 = newarray.length;
int len2 = arraytobecopied.length;
float[] result = Arrays.copyOf(newarray, len1 + len2);
System.arraycopy(arraytobecopied, 0, result, len1, len2);
// result now contains the concatenation of newarray and arraytobecopied
Note that you cannot change the length of an array object; you can only reassign the variable to a new array (e.g., newarray = result;).
The easiest can be:
List<Float> floats = new ArrayList(arraytobecopied);
floats.addAll(newarray);
arraytobecopied = floats.toArray(new float[0]);
If you dont want to use anything from java.Util at all.
How about writing one method that updates the destination array with src array. Now when u copy elements make sure that the size is enough in destination array. Otherwise when you create a new array, create it with double size and copy the elements, this may help in avoiding a new array creation everytime and doing iterations to populate the complete array again after resizing.
Somewhat similar to how array list maintains size of array inside it.

Categories