How to set the dimensions of a multi-dimensional array? [duplicate] - java

Suppose we have the Java code:
Object arr = Array.newInstance(Array.class, 5);
Would that run? As a further note, what if we were to try something like this:
Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
Array.set(arr1, 1, arr3);
Would arr1 then be a 2D array equivalent to:
String[2][4] arr1;
How about this: what if we don't know the dimensions of this array until runtime?
Edit: if this helps (I'm sure it would...) we're trying to parse an array of unknown dimensions from a String of the form
[value1, value2, ...]
or
[ [value11, value12, ...] [value21, value22, ...] ...]
And so on
Edit2: In case someone as stupid as I am tries this junk, here's a version that at least compiles and runs. Whether or not the logic is sound is another question entirely...
Object arr1 = Array.newInstance(Object.class, x);
Object arr11 = Array.newInstance(Object.class, y);
Object arr12 = Array.newInstance(Object.class, y);
...
Object arr1x = Array.newInstance(Object.class, y);
Array.set(arr1, 0, arr11);
Array.set(arr1, 1, arr12);
...
Array.set(arr1, x-1, arr1x);
And so on. It just has to be a giant nested array of Objects

It is actually possible to do in java. (I'm a bit surprised I must say.)
Disclaimer; I never ever want to see this code anywhere else than as an answer to this question. I strongly encourage you to use Lists.
import java.lang.reflect.Array;
import java.util.*;
public class Test {
public static int[] tail(int[] arr) {
return Arrays.copyOfRange(arr, 1, arr.length);
}
public static void setValue(Object array, String value, int... indecies) {
if (indecies.length == 1)
((String[]) array)[indecies[0]] = value;
else
setValue(Array.get(array, indecies[0]), value, tail(indecies));
}
public static void fillWithSomeValues(Object array, String v, int... sizes) {
for (int i = 0; i < sizes[0]; i++)
if (sizes.length == 1)
((String[]) array)[i] = v + i;
else
fillWithSomeValues(Array.get(array, i), v + i, tail(sizes));
}
public static void main(String[] args) {
// Randomly choose number of dimensions (1, 2 or 3) at runtime.
Random r = new Random();
int dims = 1 + r.nextInt(3);
// Randomly choose array lengths (1, 2 or 3) at runtime.
int[] sizes = new int[dims];
for (int i = 0; i < sizes.length; i++)
sizes[i] = 1 + r.nextInt(3);
// Create array
System.out.println("Creating array with dimensions / sizes: " +
Arrays.toString(sizes).replaceAll(", ", "]["));
Object multiDimArray = Array.newInstance(String.class, sizes);
// Fill with some
fillWithSomeValues(multiDimArray, "pos ", sizes);
System.out.println(Arrays.deepToString((Object[]) multiDimArray));
}
}
Example Output:
Creating array with dimensions / sizes: [2][3][2]
[[[pos 000, pos 001], [pos 010, pos 011], [pos 020, pos 021]],
[[pos 100, pos 101], [pos 110, pos 111], [pos 120, pos 121]]]

Arrays are type-safe in java - that applies to simple arrays and "multi-dimensional" arrays - i.e. arrays of arrays.
If the depth of nesting is variable at runtime, then the best you can do is to use an array that corresponds to the known minimum nesting depth (presumably 1.) The elements in this array with then either be simple elements, or if further nesting is required, another array. An Object[] array will allow you to do this, since nested arrays themselves are also considered Objects, and so fit within the type system.
If the nesting is completely regular, then you can preempt this regularity and create an appropriate multimensional array, using Array.newInstance(String.class, dimension1, dimension2, ...), If nesting is irregular, you will be better off using nested lists, which allow for a "jagged" structure and dynamic sizing. You can have a jagged structure, at the expence of generics. Generics cannot be used if the structure is jagged since some elements may be simple items while other elements may be further nested lists.

So you can pass multiple dimensions to Array.newInstance, but that forces a fixed length for each dimension. If that's OK, you can use this:
// We already know from scanning the input that we need a 2 x 4 array.
// Obviously this array would be created some other way. Probably through
// a List.toArray operation.
final int[] dimensions = new int[2];
dimensions[0] = 2;
dimensions[1] = 4;
// Create the array, giving the dimensions as the second input.
Object array = Array.newInstance(String.class, dimensions);
// At this point, array is a String[2][4].
// It looks like this, when the first dimension is output:
// [[Ljava.lang.String;#3e25a5, [Ljava.lang.String;#19821f]
//
// The second dimensions look like this:
// [null, null, null, null]
The other option would be to build them up from the bottom, using getClass on the previous level of array as the input for the next level. The following code runs and produces a jagged array as defined by the nodes:
import java.lang.reflect.Array;
public class DynamicArrayTest
{
private static class Node
{
public java.util.List<Node> children = new java.util.LinkedList<Node>();
public int length = 0;
}
public static void main(String[] args)
{
Node node1 = new Node();
node1.length = 1;
Node node2 = new Node();
node2.length = 2;
Node node3 = new Node();
node3.length = 3;
Node node4 = new Node();
node4.children.add(node1);
node4.children.add(node2);
Node node5 = new Node();
node5.children.add(node3);
Node node6 = new Node();
node6.children.add(node4);
node6.children.add(node5);
Object array = createArray(String.class, node6);
outputArray(array); System.out.println();
}
private static Object createArray(Class<?> type, Node root)
{
if (root.length != 0)
{
return Array.newInstance(type, root.length);
}
else
{
java.util.List<Object> children = new java.util.ArrayList<Object>(root.children.size());
for(Node child : root.children)
{
children.add(createArray(type, child));
}
Object array = Array.newInstance(children.get(0).getClass(), children.size());
for(int i = 0; i < Array.getLength(array); ++i)
{
Array.set(array, i, children.get(i));
}
return array;
}
}
private static void outputArray(Object array)
{
System.out.print("[ ");
for(int i = 0; i < Array.getLength(array); ++i)
{
Object element = Array.get(array, i);
if (element != null && element.getClass().isArray())
outputArray(element);
else
System.out.print(element);
System.out.print(", ");
}
System.out.print("]");
}
}

As a further note, what if we were to try something like this:
Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
...
No, you can't set an String[] value like that. You run into
Exception in thread "main" java.lang.IllegalArgumentException: array element type mismatch
at java.lang.reflect.Array.set(Native Method)
at Test.main(Test.java:12)

Ok, if you are unsure of the dimensions of the array, then the following method won't work. However, if you do know the dimensions, do not use reflection. Do the following:
You can dynamically build 2d arrays much easier than that.
int x = //some value
int y = //some other value
String[][] arr = new String[x][y];
This will 'dynamically' create an x by y 2d array.

So I came across this question with code to extract coefficients from a polynomial with variable numbers of variables. So a user might
want the coefficient array for a polynomial in two variables 3 x^2 + 2 x y or it could be one with three variables. Ideally, you want a multiple dimension array which the user can easily interrogate so can be cast to
Integer[], Integer[][] etc.
This basically uses the same technique as jdmichal's answer, using the Array.newInstance(obj.getClass(), size) method. For a multi dimensional arrays obj can be an array of one less dimension.
Sample code with randomly created elements
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Random;
public class MultiDimArray {
static Random rand = new Random();
/**
* Create an multi-dimensional array
* #param depth number of dimensions
* #return
*/
static Object buildArray(int depth) {
if(depth ==1) { // For 1D case just use a normal array
int size = rand.nextInt(3)+1;
Integer[] res = new Integer[size];
for(int i=0;i<size;++i) {
res[i] = new Integer(i);
}
return res;
}
// 2 or more dimensions, using recursion
int size = rand.nextInt(3)+1;
// Need to get first items so can find its class
Object ele0 = buildArray(depth-1);
// create array of correct type
Object res = Array.newInstance(ele0.getClass(), size);
Array.set(res, 0, ele0);
for(int i=1;i<size;++i) {
Array.set(res, i, buildArray(depth-1));
}
return res;
}
public static void main(String[] args) {
Integer[] oneD = (Integer[]) buildArray(1);
System.out.println(Arrays.deepToString(oneD));
Integer[][] twoD = (Integer[][]) buildArray(2);
System.out.println(Arrays.deepToString(twoD));
Integer[][][] threeD = (Integer[][][]) buildArray(3);
System.out.println(Arrays.deepToString(threeD));
}
}

Effective Java item # (I don't remember ) : Know and use the libraries.
You can use a List and use the toArray method:
List<String[]> twoDimension = new ArrayList<String[]>();
To convert it to an array you would use:
String [][] theArray = twoDimension.toArray( new String[twoDimension.size()][] );
The trick is, the outer array is declared to hold String[] ( string arrays ) which in turn can be dynamically created with another List<String> or, if your're parsing strings with the String.split method.
Demo
Focusing on the dynamic creation of the array and not in the parsing, here's an example on how does it works used in conjunction with String.split
// and array which contains N elements of M size
String input = "[[1],[2,3],[4,5,6,7],[8,9,10,11,12,13]]";
// Declare your dynamic array
List<String[]> multiDimArray = new ArrayList<String[]>();
// split where ],[ is found, just ignore the leading [[ and the trailing ]]
String [] parts = input.replaceAll("\\[\\[|\\]\\]","")
.split("\\],\\[");
// now split by comma and add it to the list
for( String s : parts ){
multiDimArray.add( s.split(",") ) ;
}
String [][] result = multiDimArray.toArray( new String[multiDimArray.size()][]);
There. Now your result is a two dimensional dynamically created array containing : [[1], [2, 3], [4, 5, 6, 7], [8, 9, 10, 11, 12, 13]] as expected.
Here's a complete running demo, which also adds more regexp to the mix, to eliminate white spaces.
I let you handle the other scenarios.

Related

How to add number in beginning in array java

In array, How do we put new integers in the beginning? I know how to add in the last. But can anyone teach me how to add in the front of the array?
int[]b=new int[a.length+1];
for (int i=0; i<a.length;i++) {
b[i]=a[i];
}
b[a.length]=0;
return b;
For this answer I assume that your ARRAY has a blank box (free position) to spare for the new element. Then it will be very easy.
System.arraycopy(yourArray, 0, yourArray, 1, yourArray.length - 1);
yourArray[0] = newElement;
You don't need a temp array if yourArray can have an additional element. arraycopy() can do all the hardwork of creating temp array, copying values, etc. for you. Make sure BOTH srcPos and destPos are same which is yourArray
Here is the full demo:
public static void main(String[] args) {
int[] yourArray = new int[5];
Arrays.fill(yourArray, 0, 4, 1);
System.out.println("Assume your array looks like this (with additional blank box for new element): " + Arrays.toString(yourArray));
int newElement = 5000;
System.arraycopy(yourArray, 0, yourArray, 1, yourArray.length - 1);
yourArray[0] = newElement;
System.out.println(Arrays.toString(yourArray));
}
If in case you DON'T have any extra space in your array already, you need another array as a placeholder with extra space (finalArray). Instead of having same array in both places, just change destPos to finalArray.
Here is the demo for that:
public static void main(String[] args) {
int[] yourArray = new int[5];
Arrays.fill(yourArray, 0, 5, 1);
System.out.println("Assume your array looks like this (withOUT additional blank box for new element): " + Arrays.toString(yourArray));
int newElement = 5000;
int[] finalArray = new int[yourArray.length + 1];
System.arraycopy(yourArray, 0, finalArray, 1, yourArray.length);
finalArray[0] = newElement;
System.out.println(Arrays.toString(finalArray));
}
If you use an array you can only add elements based on the position. If you want to add a new element to the beginning then you need to shift all other elements one position to the right. Also, keep in mind that you can not change the size of the array.
The sifting would look something like this. N being the position you are placing the new element to.
temp=a[n+1];
for(i=n+1;i>a.length-1;i++)
{
a[i]=a[i+1];
}
a[a.length-1]=temp;
It is almost the same operation, reversed and with a simple trick.
You want to add a new element, so you must create an array big enough to host it, as you did, setting its length as 1 + a.length.
Then you may set the first element to the value you desire to add, I'll write MY_VALUE.
Now you want to fill up the array: this means you have to iterate from index 1 (as 0 has already been filled with MY_VALUE) until we reach b.length - 1.
While iterating, remember that b is bigger than a, plus you're starting with index i = 1, so while this is good for b, you need to adjust it for a, so you'll have to iterate over it "one step less". To do this, you simply have to access all i-1 elements from a, as you can see from the code below.
int[] b = new int[a.length+1];
b[0] = 0;
for (int i = 1; i < b.length; i++) {
b[i] = a[i-1];
}
return b;
You need to create a temporary array ,assign the first position with new element and then copy all the elements in the old array to the new temporary array.
Example:
import java.util.Arrays;
public class Test
{
public static void main(String[] args) {
int[] arrayElements = new int[]{1,2,3,4,5,6,7};
int newElement=0;
int[] tempArr = new int[arrayElements.length + 1];
tempArr[0] = newElement;
System.arraycopy(arrayElements, 0, tempArr, 1, arrayElements.length);
Arrays.stream(tempArr).forEach(System.out::println);
}
}

How to remove and add element from java array

I have a java array. I want to remove first d items from array and store it to some other array. I am able to store but not able to remove. My Code
private static void itemRemove(int[] inputArr, int d) {
int newArr [] = new int[d];
for(int i=0;i<d;i++){
newArr[i] = inputArr[i];
}
itemPrint(inputArr);
itemPrint(newArr);
}
So in example suppose I have array
inputArr is [1,2,3,4,5] and my d is 2
I am able to add in to newArray [1,2] but not able to remove from inputArr.
Also once I remove two element from inputArr which is having size 5 so I can add two more element. Can anybody give some idea how to add element.
You need to create a new int[]array of size inputArr.length - d and copy the values:
private static int[] itemRemove(int[] inputArr, int d) {
int[] newArrd = new int[d];
int[] newArr = new int[inputArr.length-d];
int newArrIdx = 0;
for(int i=0;i<inputArr.length;i++){
if(i<d){
newArrd[i] = inputArr[i];
}else{
newArr[newArrIdx++] = inputArr[i];
}
}
return newArr;
}
You can do it using System.arrayCopy and Arrays.fill functions
int[] inputArr = {1,2,3,4,5};
int n = 3; //number of positions to move
int[] newArray = new int[n];//creating new array of size n
System.arraycopy(inputArr, 0, newArray, 0, n);//copying elements up to nth position to new array
System.arraycopy(inputArr, n, inputArr, 0, inputArr.length-n);//copying remaining elements to start position
Arrays.fill(inputArr, inputArr.length-n, inputArr.length, 0);//filling cells after the last element with default 0 value
itemPrint(newArray);
itemPrint(inputArr);
To remove element from Array you need to remove the existing index of that element as well.
As array in java is immutable so you need to re-assign the array values to new array as you are doing already with newArr[index]
Just to remove array elements without altering index you may use the predefined library of commons.apache.org like this:
array = ArrayUtils.removeElement(array, element)
Apache Common
Or, you may use the arraylist instead of this for dynamic sizing of the array.You can initialize your input array like this:
ArrayList<> inputArr= new ArrayList<>();
To remove element from inputArr with index position just use the remove(int index) method of list.
inputArr.remove(your index here);
You're not doing any removal here:
for(int i=0;i<d;i++){
newArr[i] = inputArr[i];
}
You just copy the the value from the input array to the new array. The input array is unchanged.
Arrays in Java are of a fixed size so there is no way to remove elements. The typical way you can approximate this is to replace the element with some marker (or 'sentinel') value. For objects, this could be null. For primitive values, such as integers, you might just need to choose a value arbitrarily:
for(int i = 0; i < d; i++) {
newArr[i] = inputArr[i];
inputArr[i] = -999; //marked for removal
}
This is obviously not a very good solution. What if -999 is already in the array?
The correct way to deal with this is to use a List. Lists are not fixed-size, so it is possible to remove elements. There are multiple implementations you can use. ArrayList is the closest to an array.
Your function, changed to use an ArrayList, might look like this:
private static void itemRemove(List<Integer> inputArr, int d) {
List<Integer> newArr = new ArrayList<>();
int removed = 0;
while (removed < d)
{
newArr.add(inputArr.remove(0));
removed++;
}
itemPrint(inputArr);
itemPrint(newArr);
}
There's a few different things going on here. Most notably, we had an int[] and now we have a List<Integer>. We're using what's called "generics" and generics don't work with primitive types, so we need to use what's called the "boxed type".
The other noticeable change is that the loop is different. There are difficulties removing from collections while you are iterating over them and I structured the loop differently to avoid this problem.
You can do something like this:
public class Test {
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6};
System.out.println("Original Array");
itemPrint(array);
itemRemove(array, 2);
array = itemsLeft(array,2);
System.out.println("Original Array After Removing Items");
itemPrint(array);
}
private static void itemRemove(int[] inputArr, int d) {
int newArr [] = new int[d];
for(int i=0;i<d;i++) newArr[i] = inputArr[i];
System.out.println("New Array");
itemPrint(newArr);
}
private static void itemPrint(int[] array) {
for(Integer i : array) System.out.println(i);
}
private static int[] itemsLeft(int[] inputArr, int d) {
int [] itemsLeftArr = new int[inputArr.length-d];
for(int i=d, j=0; i<inputArr.length; i++, j++) {
itemsLeftArr[j] = inputArr[i];
}
return itemsLeftArr;
}
}
Output:
Original Array
1
2
3
4
5
6
New Array
1
2
Original Array After Removing Items
3
4
5
6
Elements cannot be removed from arrays. The only thing you can do is copy other elements to overwrite them. So, if your array looks like this:
1 2 3 4 5
You can copy 3, 4 and 5 down to overwrite 1 and 2, so you will be left with this:
3 4 5 4 5
(note how 4 and 5 are still there)
And then you can overwrite the last two elements with the new elements that you want to store in the array, which will leave you with this:
3 4 5 6 7
To copy elements, you can do it manually with a for loop, or you can use System.arrayCopy().

Need help creating a method that returns an array whose elements are squares of another array

I have an assignment that requires me to create a method that takes an array of double named dArray as parameter and returns another array whose elements are squares of the elements of dArray.
For example,
if dArray is {1, 4, 6, 7}, the the returned array will be {1, 16, 36, 49}.
Any help would be greatly appreciated!
Here is what I have written so far, but it doesn't work right.
public static double[] squareArray(double[] dArray) {
double[] squareArray = new double[10];
for(int i = 0; i < dArray.length ; i++) {
dArray[] = dArray * dArray;
}
return squareArray;
}
class Test {
public static void main(String [ ] args) {
double[] scores = {3, 9, 3, 3};
double[] scoresSquared = squareArray(scores);
for (int i =0; i <scoresSquared.length; i++) {
System.out.println(scoresSquared[i] + " ");
}
}
public static double[] squareArray(double[] dArray){
double[] squareArray = new double[dArray.length];
for (int i = 0; i < dArray.length ; i++){
squareArray[i]= dArray[i] * dArray[i];
}
return squareArray;
}
}
It would appear that you are squaring the array more than you need to. If every element in the array needs to be squared, you should only have to loop over that array once, but in your code you have two loops.
That's part of the issue.
Another is that you're trying to multiply arrays, which isn't allowed. Inside that method, you need to loop over the array and square each element in it.
Try this:
In your squareArray(), create a List< Double> or something like that.
Iterate through each double in the double[] and add that double squared to the List.
Return (listname).toArray();
You're almost there.
Copy the contents of the array you're receiving and place them into your internal squareArray.
Iterate over squareArray and apply your algorithm (to access specific indexes while in the loop, use squareArray[i])
Return squareArray.

Is it possible to dynamically build a multi-dimensional array in Java?

Suppose we have the Java code:
Object arr = Array.newInstance(Array.class, 5);
Would that run? As a further note, what if we were to try something like this:
Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
Array.set(arr1, 1, arr3);
Would arr1 then be a 2D array equivalent to:
String[2][4] arr1;
How about this: what if we don't know the dimensions of this array until runtime?
Edit: if this helps (I'm sure it would...) we're trying to parse an array of unknown dimensions from a String of the form
[value1, value2, ...]
or
[ [value11, value12, ...] [value21, value22, ...] ...]
And so on
Edit2: In case someone as stupid as I am tries this junk, here's a version that at least compiles and runs. Whether or not the logic is sound is another question entirely...
Object arr1 = Array.newInstance(Object.class, x);
Object arr11 = Array.newInstance(Object.class, y);
Object arr12 = Array.newInstance(Object.class, y);
...
Object arr1x = Array.newInstance(Object.class, y);
Array.set(arr1, 0, arr11);
Array.set(arr1, 1, arr12);
...
Array.set(arr1, x-1, arr1x);
And so on. It just has to be a giant nested array of Objects
It is actually possible to do in java. (I'm a bit surprised I must say.)
Disclaimer; I never ever want to see this code anywhere else than as an answer to this question. I strongly encourage you to use Lists.
import java.lang.reflect.Array;
import java.util.*;
public class Test {
public static int[] tail(int[] arr) {
return Arrays.copyOfRange(arr, 1, arr.length);
}
public static void setValue(Object array, String value, int... indecies) {
if (indecies.length == 1)
((String[]) array)[indecies[0]] = value;
else
setValue(Array.get(array, indecies[0]), value, tail(indecies));
}
public static void fillWithSomeValues(Object array, String v, int... sizes) {
for (int i = 0; i < sizes[0]; i++)
if (sizes.length == 1)
((String[]) array)[i] = v + i;
else
fillWithSomeValues(Array.get(array, i), v + i, tail(sizes));
}
public static void main(String[] args) {
// Randomly choose number of dimensions (1, 2 or 3) at runtime.
Random r = new Random();
int dims = 1 + r.nextInt(3);
// Randomly choose array lengths (1, 2 or 3) at runtime.
int[] sizes = new int[dims];
for (int i = 0; i < sizes.length; i++)
sizes[i] = 1 + r.nextInt(3);
// Create array
System.out.println("Creating array with dimensions / sizes: " +
Arrays.toString(sizes).replaceAll(", ", "]["));
Object multiDimArray = Array.newInstance(String.class, sizes);
// Fill with some
fillWithSomeValues(multiDimArray, "pos ", sizes);
System.out.println(Arrays.deepToString((Object[]) multiDimArray));
}
}
Example Output:
Creating array with dimensions / sizes: [2][3][2]
[[[pos 000, pos 001], [pos 010, pos 011], [pos 020, pos 021]],
[[pos 100, pos 101], [pos 110, pos 111], [pos 120, pos 121]]]
Arrays are type-safe in java - that applies to simple arrays and "multi-dimensional" arrays - i.e. arrays of arrays.
If the depth of nesting is variable at runtime, then the best you can do is to use an array that corresponds to the known minimum nesting depth (presumably 1.) The elements in this array with then either be simple elements, or if further nesting is required, another array. An Object[] array will allow you to do this, since nested arrays themselves are also considered Objects, and so fit within the type system.
If the nesting is completely regular, then you can preempt this regularity and create an appropriate multimensional array, using Array.newInstance(String.class, dimension1, dimension2, ...), If nesting is irregular, you will be better off using nested lists, which allow for a "jagged" structure and dynamic sizing. You can have a jagged structure, at the expence of generics. Generics cannot be used if the structure is jagged since some elements may be simple items while other elements may be further nested lists.
So you can pass multiple dimensions to Array.newInstance, but that forces a fixed length for each dimension. If that's OK, you can use this:
// We already know from scanning the input that we need a 2 x 4 array.
// Obviously this array would be created some other way. Probably through
// a List.toArray operation.
final int[] dimensions = new int[2];
dimensions[0] = 2;
dimensions[1] = 4;
// Create the array, giving the dimensions as the second input.
Object array = Array.newInstance(String.class, dimensions);
// At this point, array is a String[2][4].
// It looks like this, when the first dimension is output:
// [[Ljava.lang.String;#3e25a5, [Ljava.lang.String;#19821f]
//
// The second dimensions look like this:
// [null, null, null, null]
The other option would be to build them up from the bottom, using getClass on the previous level of array as the input for the next level. The following code runs and produces a jagged array as defined by the nodes:
import java.lang.reflect.Array;
public class DynamicArrayTest
{
private static class Node
{
public java.util.List<Node> children = new java.util.LinkedList<Node>();
public int length = 0;
}
public static void main(String[] args)
{
Node node1 = new Node();
node1.length = 1;
Node node2 = new Node();
node2.length = 2;
Node node3 = new Node();
node3.length = 3;
Node node4 = new Node();
node4.children.add(node1);
node4.children.add(node2);
Node node5 = new Node();
node5.children.add(node3);
Node node6 = new Node();
node6.children.add(node4);
node6.children.add(node5);
Object array = createArray(String.class, node6);
outputArray(array); System.out.println();
}
private static Object createArray(Class<?> type, Node root)
{
if (root.length != 0)
{
return Array.newInstance(type, root.length);
}
else
{
java.util.List<Object> children = new java.util.ArrayList<Object>(root.children.size());
for(Node child : root.children)
{
children.add(createArray(type, child));
}
Object array = Array.newInstance(children.get(0).getClass(), children.size());
for(int i = 0; i < Array.getLength(array); ++i)
{
Array.set(array, i, children.get(i));
}
return array;
}
}
private static void outputArray(Object array)
{
System.out.print("[ ");
for(int i = 0; i < Array.getLength(array); ++i)
{
Object element = Array.get(array, i);
if (element != null && element.getClass().isArray())
outputArray(element);
else
System.out.print(element);
System.out.print(", ");
}
System.out.print("]");
}
}
As a further note, what if we were to try something like this:
Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
...
No, you can't set an String[] value like that. You run into
Exception in thread "main" java.lang.IllegalArgumentException: array element type mismatch
at java.lang.reflect.Array.set(Native Method)
at Test.main(Test.java:12)
Ok, if you are unsure of the dimensions of the array, then the following method won't work. However, if you do know the dimensions, do not use reflection. Do the following:
You can dynamically build 2d arrays much easier than that.
int x = //some value
int y = //some other value
String[][] arr = new String[x][y];
This will 'dynamically' create an x by y 2d array.
So I came across this question with code to extract coefficients from a polynomial with variable numbers of variables. So a user might
want the coefficient array for a polynomial in two variables 3 x^2 + 2 x y or it could be one with three variables. Ideally, you want a multiple dimension array which the user can easily interrogate so can be cast to
Integer[], Integer[][] etc.
This basically uses the same technique as jdmichal's answer, using the Array.newInstance(obj.getClass(), size) method. For a multi dimensional arrays obj can be an array of one less dimension.
Sample code with randomly created elements
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Random;
public class MultiDimArray {
static Random rand = new Random();
/**
* Create an multi-dimensional array
* #param depth number of dimensions
* #return
*/
static Object buildArray(int depth) {
if(depth ==1) { // For 1D case just use a normal array
int size = rand.nextInt(3)+1;
Integer[] res = new Integer[size];
for(int i=0;i<size;++i) {
res[i] = new Integer(i);
}
return res;
}
// 2 or more dimensions, using recursion
int size = rand.nextInt(3)+1;
// Need to get first items so can find its class
Object ele0 = buildArray(depth-1);
// create array of correct type
Object res = Array.newInstance(ele0.getClass(), size);
Array.set(res, 0, ele0);
for(int i=1;i<size;++i) {
Array.set(res, i, buildArray(depth-1));
}
return res;
}
public static void main(String[] args) {
Integer[] oneD = (Integer[]) buildArray(1);
System.out.println(Arrays.deepToString(oneD));
Integer[][] twoD = (Integer[][]) buildArray(2);
System.out.println(Arrays.deepToString(twoD));
Integer[][][] threeD = (Integer[][][]) buildArray(3);
System.out.println(Arrays.deepToString(threeD));
}
}
Effective Java item # (I don't remember ) : Know and use the libraries.
You can use a List and use the toArray method:
List<String[]> twoDimension = new ArrayList<String[]>();
To convert it to an array you would use:
String [][] theArray = twoDimension.toArray( new String[twoDimension.size()][] );
The trick is, the outer array is declared to hold String[] ( string arrays ) which in turn can be dynamically created with another List<String> or, if your're parsing strings with the String.split method.
Demo
Focusing on the dynamic creation of the array and not in the parsing, here's an example on how does it works used in conjunction with String.split
// and array which contains N elements of M size
String input = "[[1],[2,3],[4,5,6,7],[8,9,10,11,12,13]]";
// Declare your dynamic array
List<String[]> multiDimArray = new ArrayList<String[]>();
// split where ],[ is found, just ignore the leading [[ and the trailing ]]
String [] parts = input.replaceAll("\\[\\[|\\]\\]","")
.split("\\],\\[");
// now split by comma and add it to the list
for( String s : parts ){
multiDimArray.add( s.split(",") ) ;
}
String [][] result = multiDimArray.toArray( new String[multiDimArray.size()][]);
There. Now your result is a two dimensional dynamically created array containing : [[1], [2, 3], [4, 5, 6, 7], [8, 9, 10, 11, 12, 13]] as expected.
Here's a complete running demo, which also adds more regexp to the mix, to eliminate white spaces.
I let you handle the other scenarios.

Shorten array length once element is remove in Java

Note:
Following is my homework/assignment, feel free not to answer if you will.
I want to delete/remove an element from an String array(Set) basic, I'm not allowed to use Collections..etc.
Now I have this:
void remove(String newValue) {
for ( int i = 0; i < setElements.length; i++) {
if ( setElements[i] == newValue ) {
setElements[i] = "";
}
}
}
I does what I want as it remove the element from an array but it doesn't shorten the length. The following is the output, basically it remove the element indexed #1.
D:\javaprojects>java SetsDemo
Enter string element to be added
A
You entered A
Set size is: 5
Member elements on index: 0 A
Member elements on index: 1 b
Member elements on index: 2 hello
Member elements on index: 3 world
Member elements on index: 4 six
Set size is: 5
Member elements on index: 0 A
Member elements on index: 1
Member elements on index: 2 hello
Member elements on index: 3 world
Member elements on index: 4 six
You can't change the length of an array object once it's created. Here's an excerpt from JLS 10.2. Array Variables:
Once an array object is created, its length never changes. To make an array variable refer to an array of different length, a reference to a different array must be assigned to the variable.
This means that for this problem, you'd have to allocate a new array that's one-element shorter than the original array, and copy over the remaining elements.
If you need to remove element at index k, and the original array has L elements, then you need to copy over elements (upper bounds are exclusive):
From [0,k) to [0,k) (k elements)
From [k+1,L) to [k,L-1) (L-k-1 elements).
For a total of L-1 elements copied
static String[] removeAt(int k, String[] arr) {
final int L = arr.length;
String[] ret = new String[L - 1];
System.arraycopy(arr, 0, ret, 0, k);
System.arraycopy(arr, k + 1, ret, k, L - k - 1);
return ret;
}
static void print(String[] arr) {
System.out.println(Arrays.toString(arr));
}
public static void main(String[] args) {
String[] arr = { "a", "b", "c", "d", "e" };
print(arr); // prints "[a, b, c, d, e]"
arr = removeAt(0, arr);
print(arr); // prints "[b, c, d, e]"
arr = removeAt(3, arr);
print(arr); // prints "[b, c, d]"
arr = removeAt(1, arr);
print(arr); // prints "[b, d]"
arr = removeAt(0, arr);
arr = removeAt(0, arr);
print(arr); // prints "[]"
}
This uses System.arraycopy; you can always write your own if this isn't allowed.
static void arraycopy(String[] src, int from, String[] dst, int to, int L) {
for (int i = 0; i < L; i++) {
dst[to + i] = src[from + i];
}
}
This is a simplistic implementation that doesn't handle src == dst, but it's sufficient in this case.
See also
In java to remove an element in an array can you set it to null?
Answer: NO!
Note on == for String comparison
Most of the time, using == to compare String objects is a mistake. You should use equals instead.
String ha1 = new String("ha");
String ha2 = new String("ha");
System.out.println(ha1 == ha2); // prints "false"
System.out.println(ha1.equals(ha2)); // prints "true"
See also
Java String.equals versus ==
Difference Between Equals and ==
why equals() method when we have == operator?
The size of an array in Java can't be changed once the array is created. The following links should help you with transferring the existing items to a new array :-)
See: System.arraycopy and Array.copyOf(*).
Basically you need to create a new array which is as long as the old array's length minus 1 and then you need to copy the valid elements from the old to the new array in a loop and then replace the old array with the new array.
Since this is homework, details are left away. Feel free to post a comment for a bit more clarification.
All that setElements[i] = ""; does is change the value of an element in the array. It does not actually remove anything from the array. If you were using a collection class and called remove(i) on it, then you would actually be removing that element from the collection. But here, you're just changing its value. However, arrays in Java have a fixed size and cannot be resized, so there is no way to remove elements from them. The solution, therefore, is to create a new array with a length one shorter than the old one, and then copy all of the values that you want to keep into the new one. So,
Create new array with a length of setElements.length - 1.
Copy all of the elements in setElements into the new array, except for the one which you're looking to remove. Be careful of the fact that the indices into the two arrays will be off by one rather than equal once you've reached the index for the element that you wish to remove.
Set setElements to the new array if you want to keep using the same variable for your array.
void remove(String newValue) {
if(setElements.length == 0) return;
String [] array = new String[setElements.length-1];
int j = 0;
for ( int i = 0; i < setElements.length; i++) {
if ( setElements[i] != newValue ) {
array[j++] = setElements[i];
}
}
setElements = array;
}

Categories