I'm having a problem in my code. I have an object that contains a matrix of integers, and I'm using this matrix as the original "model" to create other matrices. But at the end, my original matrix has a different value, but I'm not changing in any way.
public Matrix generateAdjacencyMatrix(Matrix m)
{
int storedValue;
int fitness;
int[][] auxiliar_matrix = mc.matrixStructure.matrix;
int[] original_ordering = mc.matrixStructure.matrixOrder;
for(int i=0;i<mc.matrixStructure.getMatrixSize();i++)
{
if(m.matrixOrder[i] != original_ordering[i]) //Only changes if the columns have changed
{
for(int j=0;j<mc.matrixStructure.getMatrixSize();j++)
{
storedValue = auxiliar_matrix[j][m.matrixOrder[i]];
auxiliar_matrix[j][m.matrixOrder[i]] = auxiliar_matrix[j][original_ordering[i]];
auxiliar_matrix[j][original_ordering[i]] = storedValue;
}
for(int j=0;j<mc.matrixStructure.getMatrixSize();j++)
{
storedValue = auxiliar_matrix[m.matrixOrder[i]][j];
auxiliar_matrix[m.matrixOrder[i]][j] = auxiliar_matrix[original_ordering[i]][j];
auxiliar_matrix[original_ordering[i]][j] = storedValue;
}
}
}
m.matrix = auxiliar_matrix;
m.setFitness(computeFitness(m.matrix));
return m;
}
This is the method that creates the other matrices. The object "mc" contains my original matrix (mc.matrixStructure.matrix), and exactly after the for loop the value is different.
I am instantiating this object on the constructor method:
public GeneticAlgorithm() throws IOException
{
this.r = new Random();
this.matingPool = new ArrayList<>(populationSize);
this.population = new ArrayList<>(populationSize);
this.nextGeneration = new ArrayList<>(populationSize);
this.mc = new MatrixCreator("CS4006_input_file2.txt");
this.mc.check0or1();
this.mc.checkDiagonalLine();
this.mc.checkSymmetry();
this.auxiliarVector = mc.matrixStructure.matrixOrder;
this.auxiliarMatrix = new Matrix(mc.matrixStructure.getMatrixSize());
this.matrixSize = mc.matrixStructure.getMatrixSize();
}
This is it.
When you do this ...
int[][] auxiliar_matrix = mc.matrixStructure.matrix;
int[] original_ordering = mc.matrixStructure.matrixOrder;
... you are making auxiliar_matrix and original_ordering references to the same objects that mc.matrixStructure.matrix and mc.matrixStructure.matrixOrder refer to. Modifying those objects via one set of references is equivalent to modifying them through the other, so contrary to your assertion, you absolutely are changing your original matrix. To avoid this, you need to copy the arrays.
Moreover, you have that problem twofold with auxiliar_matrix because Java 2D arrays are arrays of arrays, and arrays are objects, too. You need to perform a deep copy of that 2D array to avoid modifying the original object.
Something like this should do it:
int[] original_ordering = Arrays.copyOf(mc.matrixStructure.matrixOrder);
int[][] auxiliar_matrix = Arrays.copyOf(mc.matrixStructure.matrix);
int i;
for (i = 0; i < auxiliar_matrix.length; i += 1) {
auxiliar_matrix[i] = Arrays.copyOf(auxiliar_matrix[i]);
}
When you assign an object to a reference variable, you assign its reference. You do not copy it to that reference.
Thus, after an assignment such as
int[][] auxiliar_matrix = mc.matrixStructure.matrix;
Your auxiliar_matrix reference variable now refers to the matrix to which mc.matrixStructure.matrix refers.
It's the same matrix, residing on the heap.
Now you are changing data inside the object referred to by auxiliar_matrix. For example, here:
auxiliar_matrix[j][original_ordering[i]] = storedValue;
This means the value will be changed in the matrix both it and mc.matrixStructure.matrix are referring to.
If you want to work on a separate copy of your original matrix without affecting it, you have to copy it to a new object first, and then assign this copy to auxiliar_matrix. In this case, it's an array of arrays, so you have to create a new array of the same length, and copy over each of the subarrays using Arrays.copyOf. Beware of trying to use Arrays.copyOf on the array of arrays - the copy is shallow and it will just copy references to the subarrays which would give you the same problem.
Related
I need to be able to have an n-dimensional field where n is based on an input to the constructor. But I'm not even sure if that's possible. Is it?
Quick solution: you could approximate it with a non-generic ArrayList of ArrayList of ... going as deep as you need to. However, this may get awkward to use pretty fast.
An alternative requiring more work could be to implement your own type using an underlying flat array representation where you calculate the indexing internally, and providing accessor methods with vararg parameters. I am not sure if it is fully workable, but may be worth a try...
Rough example (not tested, no overflow checking, error handling etc. but hopefully communicates the basic idea):
class NDimensionalArray {
private Object[] array; // internal representation of the N-dimensional array
private int[] dimensions; // dimensions of the array
private int[] multipliers; // used to calculate the index in the internal array
NDimensionalArray(int... dimensions) {
int arraySize = 1;
multipliers = new int[dimensions.length];
for (int idx = dimensions.length - 1; idx >= 0; idx--) {
multipliers[idx] = arraySize;
arraySize *= dimensions[idx];
}
array = new Object[arraySize];
this.dimensions = dimensions;
}
...
public Object get(int... indices) {
assert indices.length == dimensions.length;
int internalIndex = 0;
for (int idx = 0; idx < indices.length; idx++) {
internalIndex += indices[idx] * multipliers[idx];
}
return array[internalIndex];
}
...
}
Here's a nice article that explains how to use reflection to create arrays at run-time: Java Reflection: Arrays. That article explains how to create a one-dimensional array, but java.lang.reflect.Array also contains another newInstance method to create multi-dimensional arrays. For example:
int[] dimensions = { 10, 10, 10 }; // 3-dimensional array, 10 elements per dimension
Object myArray = Array.newInstance(String.class, dimensions); // 3D array of strings
Since the number of dimensions is not known until runtime, you can only handle the array as an Object and you must use the get and set methods of the Array class to manipulate the elements of the array.
Try this:
https://github.com/adamierymenko/hyperdrive
I have to implement an array that takes its elements from a random generator. Whenever the array reaches it's last element a method resize() will be called to increase the size of the array. In my code every thing goes alight until invoking resize() method, it does not do any effect on the size of the array. It supposed to increase the size of the array to allow more elements to be entered.
for (int j=0; j<arr.length-1; j++) {
random= generator.nextInt(arr.length*4) ;
arr[j]=random;
}
if(arr_size==arr.length){
resize(arr);
for (int h=0; h<(arr.length-1)*2; h++) {
random= generator.nextInt(arr.length*4) ;
arr[h]=random;}
}
Here is resize():
private static void resize(int[] arr) {
int[] tmp = new int[2*arr.length];
System.arraycopy(arr,0,tmp,0,arr.length);
arr = tmp;
}
Setting arr = tmp does not do what you think it does. You're simply pointing the local variable arr in the resize() method to the local variable tmp. What you want to do is return tmp and assign it to arr outside of the method.
if(arr_size==arr.length){
arr = resize(arr);
And change the resize() method signature to
private static int[] resize(int[] arr) {
//Resize
return tmp;
}
The key thing to take away is that: When passing an object reference to a method in Java, you're passing a copy of that object's reference, which can be thought of as a copy of the location in memory of that object. All such manipulations to this REFERENCE in the called method won't take effect outside of the method. However, you CAN manipulate the actual object itself because, as I said, the reference is pointing to the same place in memory with the exact same object.
But changing a copy of a location in memory to point to a new location in memory does not cause the original calling object reference to point to that same location
try this :
private static int[] resize(int[] arr) {
int[] tmp = new int[2*arr.length];
System.arraycopy(tmp,0,arr,0,arr.length);
System.out.println(tmp.length);
return tmp;
}
Either set and return the tmp variable as described by Kon, or you pass in arr by reference to make changes to it persist outside of the resize function:
private static void resize(ref int[] arr) { .... }
and call it like
resize(ref arr);
When you say New int, reference is changed. Java uses Copy by Reference not exactly Pass by reference, if you change reference by new the caller method properties wont have any change, in your case have a return type and assign it back to arr.
I was doing some exercises on arrays, and I was prompted to return a reference to an array after copying it element by element. What does this exactly mean?
My code is the following:
public static int[] cloneArray(int array[])
{
int[] arraycopy = new int[array.length];
for(int i = 0; i < array.length; i++)
{
arraycopy[i] = array[i];
}
return arraycopy;
}
I don't know what I should be returning though as a "reference": should I return an array of ints or an int? Whenever I try to print the array, I get a weird combination of characters and numbers (unless I invoke Arrays.toString()).
"Return a reference to an array" just means "return an array".
Java only returns values, which are either primitives or object references (ie for objects, the value is a reference).
Although Java is based on C, it doesn't sully itself with pointers etc like C does.
In Java, arrays and objects do not act like primitive types such as int. Consider the following code:
public class MyClass {
public static int method1(int ar[]) {
int x = ar[1];
ar[1] = 3;
return x;
}
}
Now suppose that somewhere else, the follow code is executed:
int abcd[] = new int[3];
abcd[0] = 0;
abcd[1] = 1;
abcd[2] = 2;
int d = MyClass.method1(abcd);
System.out.println(abcd[1]);
What would be printed? It's not 1, but 3. This is because the method was not given the data in the array, it was told the location of the array. In other words, it was passed a reference. Because it was using a reference, changing the value of an array index changed its value in the code that called it. This would not have happened if method1 had taken an int as an argument.
Basically, in Java, methods do not accept arrays as arguments or return arrays. They only use references to arrays. The same goes for objects (except for Strings, which are passed by value).
In Java, Objects are only accessed by reference. Just return the Array object.
I am fairly new to Java and was wondering what the difference between the two is. For this example I used arrays:
class testpile {
public static void main(String[] args)
{
int[] a = {1,2,3,4,5,6}; //First array
int[] b = new int[5]; //Second Array
b[0] = 7;
b[1] = 8;
b[2] = 9;
b[3] = 10;
b[4] = 11;
print(a);
print(b);
}
public static void print(int[] a) {
for (int i = 0; i < a.length; i++)
System.out.print(a[i] + " ");
System.out.println();
}
}
I understand that using "new" creates a unique object but what are the advantages of using one over the other?
In your example there's no real difference between the two. The first is mostly just "syntactic sugar" for the latter. In both cases the array is allocated on the heap.
Both of the code creating a int array of size 5/6
In the first case the array is initialized with vale at the time of creation
In second case the value is assigned latter
that's the difference
I understand that using "new" creates a unique object but what are the advantages of using one over the other?
Both constructs do exactly the same thing (with different data, though): Creating an array and filling it with data. In particular, both these arrays are "unique objects".
You'd use the "less literal" one when you do not know the size and the initial values for the element at compile-time.
int[] a = {1,2,3,4,5,6}; //First array
int[] b = new int[5]; //Second Array
They are just two different ways of creating an array. There isn't really any OOP involved here.
The first one is better when you know the values before hand, otherwise the second is better.
The first statement is called array initialization where six int variables are created and each variable is assigned. In second statement, the new keyword create 5 int variables whose initial value is zero.
Using new keyword, you may instantiate an array whenever you require.
int []a=new int[5];
for(int i:a)
System.out.println(i);
a=new int[]{11,22,33};
for(int i:a)
System.out.println(i);
I think the result is same.
But when you create a array with "new" clause, You should assign a specify length of the array.
e.g int[] b = new int[**5**];
And in this sample, you can also assign the value for b[5]. there shouldn't produce compilation error.But the error should occur in the runtime.
In regard to the another method, the length of the array don't need specify. It depend on the element count of array.
I need to be able to have an n-dimensional field where n is based on an input to the constructor. But I'm not even sure if that's possible. Is it?
Quick solution: you could approximate it with a non-generic ArrayList of ArrayList of ... going as deep as you need to. However, this may get awkward to use pretty fast.
An alternative requiring more work could be to implement your own type using an underlying flat array representation where you calculate the indexing internally, and providing accessor methods with vararg parameters. I am not sure if it is fully workable, but may be worth a try...
Rough example (not tested, no overflow checking, error handling etc. but hopefully communicates the basic idea):
class NDimensionalArray {
private Object[] array; // internal representation of the N-dimensional array
private int[] dimensions; // dimensions of the array
private int[] multipliers; // used to calculate the index in the internal array
NDimensionalArray(int... dimensions) {
int arraySize = 1;
multipliers = new int[dimensions.length];
for (int idx = dimensions.length - 1; idx >= 0; idx--) {
multipliers[idx] = arraySize;
arraySize *= dimensions[idx];
}
array = new Object[arraySize];
this.dimensions = dimensions;
}
...
public Object get(int... indices) {
assert indices.length == dimensions.length;
int internalIndex = 0;
for (int idx = 0; idx < indices.length; idx++) {
internalIndex += indices[idx] * multipliers[idx];
}
return array[internalIndex];
}
...
}
Here's a nice article that explains how to use reflection to create arrays at run-time: Java Reflection: Arrays. That article explains how to create a one-dimensional array, but java.lang.reflect.Array also contains another newInstance method to create multi-dimensional arrays. For example:
int[] dimensions = { 10, 10, 10 }; // 3-dimensional array, 10 elements per dimension
Object myArray = Array.newInstance(String.class, dimensions); // 3D array of strings
Since the number of dimensions is not known until runtime, you can only handle the array as an Object and you must use the get and set methods of the Array class to manipulate the elements of the array.
Try this:
https://github.com/adamierymenko/hyperdrive