Creating an n-dimension Array in Java during runtime - java

I have a String which contains arrays. Example:
"[[1, 2], [4, 5], [7, 8]]"
Now, I want to make an actual Java array out of this. I have created a function to get the dimensions and a recursive function to get each and every element of the array. Thus, I have every 1-D array created, but I would like to know if there is a way in Java to create an array of the dimension that I found during the runtime? The dimension are returned as an array. Like, for the above example the dimension is:
[3, 2]
EDIT:
Is there a way to create an actual array from this information? The dimension [3, 2] is just an example. I can have [3, 2, 4, 5] as well. Can an array be generated from this information during the runtime? I do not have this information during compile time.
There is some problem, I cannot comment on answers. So, I am editing here.

If you are doing numeric work then you should probably use a library. For example my open source library Vectorz provides proper support for multidimensional arrays / matrices (with doubles).
Then you can just do something like:
INDArray m=Arrayz.parse("[[1, 2], [4, 5], [7, 8]]");
The INDArray object encapsulates all the multidimensionality so you don't need to worry about writing big nested loops all the time, plus it provides a lot of other functions and capabilities that normal Java arrays don't have.

The main problem is that you can't reference an N dimensional array in code directly.
Fortunately java has a bit of a dirty hack that lets you have some way to work with N dimensional arrays:
Arrays are objects like every other non-primative in java.
Therefore you can have:
// Note it's Object o not Object[] o
Object o = new Object [dimensionLengh];
You can use a recursive method to build it up.
Object createMultyDimArray(int [] dimensionLengths) {
return createMultyDimArray(dimensionLengths, 0);
}
Object createMultyDimArray(int [] dimensionLengths, int depth) {
Object [] dimension = new Object[dimensionLengths[depth]];
if (depth + 1 < dimensionLengths.length) {
for (int i=0; i < dimensionLengths[depth]; i++) {
dimension[i] = createMultyDimArray(dimensionLengths, depth+1);
}
}
return dimension;
}
To use this you will need to cast from Object to Object [].
Java is type safe on arrays and mistakes can cause a ClassCastException. I would recommend you also read about how to create arrays using java reflection: http://docs.oracle.com/javase/tutorial/reflect/special/arrayInstance.html.

Related

Java new ArrayList clone inefficient

I'm getting the value of an ArrayList inside an ArrayList containing integers from a HashMap. However, I need a new copy of this data; otherwise, I will be changing data inside of the HashMap, as it returns a reference.
To overcome this, I'm creating a new instance of the ArrayList Object for each inner ArrayList. Is there a better, more efficient way to achieve this result (potentially with a different data structure?), as it is taking a very long time to complete with a large amount of data.
// Example of how I am copying the data currently
ArrayList<ArrayList<Integer>> calcRes = memo.get(n - i);
ArrayList<ArrayList<Integer>> calc = new ArrayList<>();
for (ArrayList<Integer> item : calcRes) {
calc.add(new ArrayList<>(item));
}
For a bit of context of why and how I am using this, I'm solving a problem to find all the possibilities to make stairs with N blocks.
Stairs have to descend each column by at least one. For example the stairs with six blocks would return [[5, 1], [4, 2], [3, 2, 1]]. However, for larger values N, such as 200, this takes much longer so I'm trying to cache the results inside the memo. I call the function the code above is in recursively to find more solutions. However, I don't want to change the object stored in the memo. This is because I add the previous item to the start. For example, with [3, 3] (which doesn't count as a solution), I would look at the 3 on the right and call the function I'm in again, which would give me [[2, 1]]. Then I would need to add on the 3 on the left of the original to add up to 6 blocks. This is why I am creating a new instance of the ArrayList; otherwise, the memo would be changed.

Comparator for sorting 2D arrays and 1D arrays in Java

I used the following code for sorting a 2D array of int[][] type in reverse order by making use of a comparator.
int[][] arr = {{2,3},{3,5},{5,8}};
Arrays.sort(arr, (a,b) -> Integer.compare(b[1], a[1]));
But I am unable to sort a 1D array of int[] type using similar approach. On the internet I found information saying "The only way to sort a primitive array in descending order is, first sort the array in ascending order and then reverse the array in place."
Why am I able to sort a 2D array of primitive type, but not a 1D array using comparator?
It is possible to sort an int[][] in descending order because one basically compares int[]s against each others. As per JLS, ยง10: "... Arrays are objects ...".
Looking closer at the Arrays API, we find method sort(T[], Comparator<? super T>), which, together with some static builder methods from Comparator, allows to reverse-sort an array of objects:
T[] someArray = ...
Arrays.sort(someArray, Comparator.<T>naturalOrder().reversed())
Ideone Demo
This only works for object-arrays, not for primitive arrays. And for primitive arrays, we do not have any method sort(int[], Comparator<...>) in Arrays (probably because one cannot use primitives as generic types, project Valhalla may or may not change this in the future).
So yes, sorting an array of primitives and then reversing it seems like the only option if one wants to have constant memory overhead. It would look something like this (sketch):
final int[] values = { 1, 5, 3, 2, 4 };
Arrays.sort(values);
reverse(values);
Ideone Demo
There just aren't any built-in sort methods that accept a 1D primitive array and a Comparator.
As for why, only the designers can say authoratively, but here are some arguments against having them:
Primitive arrays are not used very often in Java programs to begin with.
A sort implementation that uses Comparator would need to wrap every array element in an object to pass them to the Comparator anyway, so you might as well have the user convert the array of int into an array of Integer themselves.
You would need to add 7 or 14 more Arrays.sort implementations which is a non-trivial amount of code to test
The most common use case for a custom comparator is sorting in reverse, and you can already achieve that by first sorting and then reversing
You can use Stream to convert an int to an Integer, do sort using a Comparator and reconvert it to an int[].
final int[] values = {2, 0, 5, 1, 3, 4};
int[] reversed = IntStream.of(values)
.boxed()
.sorted(Comparator.reverseOrder())
.mapToInt(i -> i)
.toArray();
System.out.println(Arrays.toString(reversed));
output:
[5, 4, 3, 2, 1, 0]

How to get unique elements from an array and length of resulting array

I have an sorted array consisting elements (1,1,2,3,3,4). I want to get unique elements from this array and length of the resulting array.
Output array should consists (1,2,3,4) and size = 4.
If you are using Java 8, you can do it in the following way:
Arrays.stream(arr).distinct().toArray();
DEMO
The easiest thing to do here might be to just add your array elements to a sorted set, e.g. TreeSet:
int[] array = new int[] {1, 1, 2, 3, 3, 4};
Set<Integer> set = new TreeSet<>();
for (int num : array) {
set.add(num);
}
This option would make good sense if your code also had a need to work with a set later on at some point.
Is this for homework? If it is, please say so. I'm going to assume it is.
I would traverse the array and use a List to store values that I have already seen. If I come across a value that already appears in my List, I'll skip it. If not, I'll add it. Then I'll convert the list to an array and return it. I'm not going to write it for you because I'm assuming it's homework, but that is the basic idea.
NOTE: If performance is a concern, use a HashMap instead of a List.

Java - array types to Object type cast

How does java convert array types to Object types ?
For example, say we have an int array 'src' and we use System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length) then how does java convert a primitive type array to an instance of Object ? Also while copying to 'dest', how does it know how to copy it without knowing the type ?
Does it just do a byte by byte copy like a clone, because when i run the following code
int[][] a = new int[][] {{1,2,3,4,5},{6,7,8,9,0}};
int[][] b = new int[a.length][a[0].length];
System.arraycopy(a,0,b,0,a.length);
System.out.println(java.util.Arrays.toString(a));
b[1][3]=100;
System.out.println(java.util.Arrays.toString(a[0]));
System.out.println(java.util.Arrays.toString(a[1]));
I get the following output
[[I#7d08c1b7, [I#49e61582]
[1, 2, 3, 4, 5]
[6, 7, 8, 100, 0]
What is the output [[I#7d08c1b7, [I#49e61582] ? Is it like the address of the array a[0] and a[1] (like array of pointers in C/C++) ?
Also how does a[1][3] change if i changed b[1][3] and what is the correct way to make a copy of a ?
EDIT: Also how does java.lang.reflect.Array.getLength(Object array) work ?
EDIT: I want to point out that I change the value of b[1][3] but while printing a[1], the value a[1][3] is also changing. Why is that happening ?
How does java convert array types to Object types ?
Array types are already a sub-class of Object, so there's no need for any conversion.
how does java convert a primitive type array to an instance of Object ? Also while copying to 'dest', how does it know how to copy it without knowing the type ?
A primitive type array is already an instance of Object, so no conversion is required. The JVM knows at runtime the types of elements stored in the source and target arrays. If they don't match, ArrayStoreException is thrown.
how does a[1][3] change if i changed b[1][3] and what is the correct way to make a copy of a ?
System.arraycopy doesn't do deep copy. It copies the primitive or reference in each position of the source array to the target array. When an element of the source array is itself a reference to a sub-array, the reference is copied to the target array as is. Therefore a[1] == b[1] (they refer to the same array object), so changing b[1][3] changes a[1][3].
If you want each sub-array to be a copy of the original sub-array, you have to execute System.arraycopy for each sub-array separately after executing System.arraycopy for the main array.
How does java convert array types to Object types ?
An array is a container object that holds a fixed number of values of a single type. It lives on the heap.
What is the output "[[I#7d08c1b7, [I#49e61582]" ? Is it like the
address of the array a[0] and a1 (like array of pointers in C/C++) ?
"[[I#7d08c1b7, [I#49e61582]" are the class names & hashcodes for a[0] & a1
Also how does a1[3] change if i changed b1[3] and what is the
correct way to make a copy of a ?
I wrote a sample code
int[] a = new int[]{1,2,3,4,5,6,7};
int[] b = new int[a.length];
b=Arrays.copyOf(a, a.length);
//System.arraycopy(a, 0, b, 0, a.length);
b[2]=789;
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
Output
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 789, 4, 5, 6, 7]
Change in b won't affect values of a.
If you want to change b & also want a subsequent change in a
just do
b=a; //now b is a shallow copy of a
Well the standard way of copying an array object is to use Arrays.copyOf method.
From Object javadocs:
The toString method for class Object returns a string consisting of
the name of the class of which the object is an instance, the at-sign
character `#', and the unsigned hexadecimal representation of the hash
code of the object. In other words, this method returns a string equal
to the value of:
`getClass().getName() + '#' + Integer.toHexString(hashCode())`
What is the output "[[I#7d08c1b7, [I#49e61582]" ? Is it like the
address of the array a[0] and a[1] (like array of pointers in C/C++) ?
It's class name and hashCode.
getClass().getName() + '#' + Integer.toHexString(hashCode())
Also how does a[1][3] change if i changed b[1][3] and what is the
correct way to make a copy of a ?
System.arraycopy will create a new array, so what changed to b, there's no impact to b.
EDIT: Also how does java.lang.reflect.Array.getLength(Object array)
work ?
If anArray is statically typed to an array type, you should use anArray.length (not a method call). You'd use the reflection form if you only had a reference to the array as Object.

Implicit Type Conversion?

I am reviewing someone else's Grails code and I see the following:
Set<Integer> weeks = new ArrayList<Integer>()
It looks like after this line is set, Grails thinks that weeks is a HashSet. I am not well versed in either Java or Grails, and the (java) documentation looks like ArrayList extends List and HashSet extends Set, but that this direct construction wouldn't work. Is this a Grails thing? Thanks.
It's somewhat unusual in Groovy to see new ArrayList<Integer>() since [] works identically and is way less verbose, so I would have written that as Set<Integer> weeks = []. Then it's a bit more clear what's going on - Groovy is converting one collection type to another, with the [] really as a convenient way to create a holder and populate the initial data (if there is any). Since there's no syntactic sugar for collections other than [] for List and [:] you need these conversions.
def weeks = [] as Set is probably the more common syntax. This is also more clear since [] is just temporary and using "as" does the conversion, and more explicitly than just declaring the type on the left side.
You can also use this to convert collections to arrays. You can't use Java syntax to create arrays since it uses braces and looks like a Closure definition, so instead of int[] numbers = new int[] { 1, 2, 3 } you have to do int[] numbers = [1, 2, 3] or def numbers = [1, 2, 3] as int[].

Categories

Resources