Java custom arrayMerge function - java

I'm trying to merge 2 int arrays using this custom function I found on Google:
public static <T> T[] arrayMerge(T[]... arrays)
{
int count = 0;
for (T[] array : arrays) count += array.length;
T[] mergedArray = (T[]) Array.newInstance(arrays[0][0].getClass(),count);
int start = 0;
for (T[] array : arrays) {
System.arraycopy(array, 0, mergedArray, start, array.length);
start += array.length;
}
return (T[]) mergedArray;
}
but I'm fail to understand what parameters this function takes. I was hoping it would work like arrayMerge(int[], int[]), but Eclipse tells me it doesn't take these arguments.
I can't Google a capital T to find an answer.
You can answer in a form or reading material, but an example of using this function to merge 2 int arrays would be nice (does it eliminate duplicates, if not, how can I also achieve that?).

The method takes any number of arrays, all having the same type:
String[] array1 = ... ;
String[] array2 = ... ;
String[] array3 = ... ;
String[] mergedArray = ArrayHelper.arrayMerge(array1, array2, array3);
However, due the way generics work in Java, you cannot pass an array of a primitive type (such as int[]).

The code you have post here is for any type of array not only int and for more than 2 arrays to merge. (unlimited)
T stand for a generic Type. see Generics in Java.
You can use only the System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src the source array.
srcPos starting position in the source array.
dest the destination array.
destPos starting position in the destination data.
length the number of array elements to be copied.
First make an array which has the length of both arrays.
public merge(int[] x, int[] y) {
int[] merged = new int[x.length + y.length]
Than copy with System.arraycopy the first array x into merged at 0.
And copy with System.arraycopy the 2nd array y into merged at x.length
But it doesn't eliminate duplicates.
For no duplicates you can use a Set. But we have to work with Integer not int.
So we have to convert to Integer an back to int. like:
HashSet<Integer> set = new HashSet<Integer>();
for( int i : x ) {
set.add( Integer.valueOf( i ) );
}
for( int i : y ) {
set.add( Integer.valueOf( i ) );
}
int[] merged = new int[set.size()];
int i = 0;
for( Integer value : set ) {
merged[i++] = value.intValue();
}

That syntax is called varargs - it means it will accept any number of parameters of that type. Removing the generics to simply the explanation, a method defined as this:
public static void someMethod(int... numbers) {
// some code
}
can be called like this:
someMethod(5); // The "numbers" parameter will be an int array size 1: [5]
someMethod(1,2,3); // The "numbers" parameter will be an int array size 3: [1, 2, 3]
someMethod(); // The "numbers" parameter will be an int array size 0: []
It's like a shorthand for this:
someMethod(new int[] {1, 2, 3});
but less ugly.
In your example, the array is a typed generic array - you don't know what the element type is until it's called.

Related

How would I add, delete or insert arrays in Java using static methods (no ArrayLists)

I am trying to self-learn Java, and have an issue with these arrays I have to make without ArrayLists. I tried to look online on static methods, but I can't find anything that could help me understand. I have to make 3 methods that can be used to modify arrays. So, for adding a value to the end of an array, the method should have the array and the value as parameters. It should then return a new array which is the same as the old array but with the added on value. The site I'm trying to learn this on shows me the block of code and explains what methods do, but it doesn't show me how to use them.
public class Arrays {
static void array() {
System.out.print("1, 2, 4, 7");
}
static void add() {
System.out.print(", 11");
}
public static void main(String[] args) {
System.out.println("Array:");
array();
System.out.println(" ");
System.out.println("Array with Added End:");
array();
add();
System.out.println(" ");
}
}
...for adding a value to the end of an array, the method should have the array and the value as parameters. It should then return a new array which is the same as the old array but with the added on value.
I'm going to assume that add is the method that will add something to your array and that your array is of type int[]. I'll build the method step-by-step:
method should have the array and the value as parameters
add(int[] arr, int val) {}
It should then return a new array which is the same as the old array
The return type of the method must therefore be the same as the array parameter arr. Since you stated the method must be static:
public static int[] add(int[] arr, int val)
{
// todo: make this work
}
It should then return a new array which is the same as the old array but with the added on value.
Arrays cannot be resized so you need to create a new array (which is also specified in the instructions) that is large enough to hold all the elements of arr plus one additional element. There are several ways to populate your new array:
Copying each element yourself:
public static int[] add(int[] arr, int val)
{
int[] newArray = new int[arr.length + 1];
for (int index = 0; index < arr.length; index++)
{
newArray[index] = arr[index];
}
// Arrays start at index 0 so arr.length will be the last
// position in newArray.
newArray[arr.length] = val;
return newArray;
}
Using java.util.Arrays:
public static int[] add(int[] arr, int val)
{
int[] newArray = Arrays.copyOf(arr, arr.length + 1);
newArray[arr.length] = val;
return newArray;
}
Using System.arraycopy:
public static int[] add(int[] arr, int val)
{
int[] newArray = new int[arr.length + 1];
System.arraycopy(arr, 0, newArray, 0, arr.length);
newArray[arr.length] = val;
return newArray;
}
This should be enough of an example on working with arrays to help you write the other two methods.

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().

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

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.

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