Make a copy of a variable and add to Arraylist - java

I'm working with two-dimensional array-values that should be inserted into a ArrayList. But this is done in a for-loop and the value of the two-dimensional array-value gets changed as the loop runs since it is just used as an temp-variable (which makes all of the variables stored in the ArrayList gets changed as this variable changes).
So if I try to print out the content of the ArrayList when the loop is done all the values are the same.
for(int i = 0; i <= Counter; i++)
{
if(Xhavetomove >= i)
arrayvalue[0][0] = this.Xspeed;
else
arrayvalue[0][0] = 0;
if(Yhavetomove >= i)
arrayvalue[0][1] = this.Xspeed;
else
arrayvalue[0][1] = 1;
System.out.println(arrayvalue[0][1]);
Object.movement.add(arrayvalue);
}
Are there anyway I can make it store the value itself?
For example: The first time the loop runs the value is "5,5" but if I print out the ArrayList when the loop is done all the values has turned into "5,1".

The problem is the way Array is added to the Object here. You are not adding the Array to the Object. What is happening is you are adding the address to the location in memory where the Array resides. So every time you add the Array to the Object, you are adding the same address every time. So every Array in the Object is actually the same Array over and over since they all point to a single location in memory. So when you change the Array, it will appear to change all of them inside the Object.
The best thing to do is either create a new Array every time through the loop, essentially creating a new location in memory for the Array to reside, or clone() the Array which will create a new reference.
Example:
String[] houseOfStark = {"Eddard", "Catelyn",
"Robb", "Sansa", "Arya", "Bran", "Rickon"}; // Sorry Jon
String[] copyOfStark = houseOfStark;
String[] cloneOfStark = houseOfStark.clone();
houseOfStark[1] = "Lady Catelyn";
System.out.println(houseOfStark[1]);
System.out.println(copyOfStark[1]);
System.out.println(cloneOfStark[1]);
Will produce:
Lady Catelyn
Lady Catelyn
Catelyn
Good blog post explaining the difference

At the end each add needs to create an own object.
To use clone is one way.
Or to add always the values in pairs, in an other.
A totally different way is to use serialization. This make sense when you do not want to calculate this values but to log it. In this case you need an outputStream
What is best is defined by what you want to do with Object.movement

You need to use array's clone() method to make its copy:
//for example
int[][] copy = (int[][])arraySource.clone();

Related

How does the method assigns the array?

I am confused about how the array was assigned to any data, as the method meant to be a self contain
or I haven't understood a fundamental concept
// Craft stall stock and till program
import java.util.Scanner;
public class revisonTest {
public static void main(String[] args) // where program exicutes
{
final int numOFitems = 50;
String[] item = new String[numOFitems];
int [] broughtItem = new int[numOFitems];
int[] costItem = new int[numOFitems];
int COUNT = getDetail(item,broughtItem,costItem);
System.out.println(item[0]);
}
public static int getDetail(String[] name,int[] quantities,int[]cost)
{
int count =1;
int arrayIndex =0;
String answer = "";
while(!(answer.equals("Exit")))
{
answer = userInput("Item"+count+": ");
if(!(answer.equals("Exit")))
{
name[arrayIndex] = answer;
quantities[arrayIndex] = Integer.parseInt(userInput("How many "+name[arrayIndex]+" have you brought? "));
cost[arrayIndex] = Integer.parseInt(userInput("How much does a "+name[arrayIndex]+" cost? "));
count++;
arrayIndex++;
}
}
return count;
}
public static String userInput(String question)
{
Scanner sc = new Scanner(System.in);
System.out.println(question);
return sc.nextLine();
}
}
String[] item = new String[numOFitems];
This first makes a new treasure map named 'item'.
This makes a new treasurechest capable of containing numOFitems treasuremaps, and buries it in the sand. It is then filled with that many blank maps that lead to no treasure.
This updates your item treasuremap to point at this treasurechest-containing-maps.
getDetail(item,broughtItem,costItem);
This takes your treasuremap to the treasure-of-maps and makes a copy of it, and then hands the copy to the getDetail method. Your copy is unmodified and cannot be modified by getDetail... but that's just your copy of the treasure MAP, not the treasure. Note that getDetail calls this copy name and not item - which it is free to do.
(in getDetail) name[arrayIndex] = answer;
This is getDetail taking its name treasuremap (which is a copy of main's item map), follows the map, gets a shovel out, digs down, finds the treasure, opens it, finds the arrayIndexth map in it, pulls it up, and copies its answer map onto it.
Thus.. when main follows its copy of its map to the same treasure, same thing happens.
Of course, in java we use different jargon.
'treasure' -> 'object'
'treasuremap' -> 'reference'
'follow the map, dig down, open treasure' -> 'dereference'.
'create treasure' -> 'instantiate an object'
There are two different concepts here:
Allocating an array and assigning an array reference to a variable, and
Assigning values to elements in the array
In main, the new operation creates an array of a certain size, and assigns a reference to that array to the variable named item.
The call of getDetail(item,...) makes a copy of that reference (not the array itself) available to the method. Inside getDetail, this reference is stored in what is effectively a local variable, named name.
The loop inside getDetail is collecting answers (which are actually String references) and storing them in successive elements of the array that it knows as name and which the caller knows as item.
name[arrayIndex] = answer;
(Similarly for the other two arrays, of course)
In summary, getDetail is provided with an existing array, into which it writes values.
Incidentally, if the user types too many answers (more than name.length) you'll run off the end of the array, and get an 'index out of bounds' exception.
A String in java is considered a non-primitive data type. So when you created your item array using:
String[] item = new String[numOFitems];
You actually created an empty array of String objects. Based on your code the array has 50 empty spaces where you can store data.
The next part of your code is designed to get input from the user and fill those arrays:
int COUNT = getDetail(item,broughtItem,costItem);
Note: getDetail() never returns the item[] array, so how do you access the data?
When you pass your item array as an argument to the getDetail() method, you are actually passing that array as a reference.
In Java, non-primitive data types are passed as reference. This means that instead of sending the data to the getDetail() method, your actually sending information about where the data is located in memory.
Within your getDetail() method you can manipulate the data and the changes will be reflected on the original array without having to return it.
That is the reason why your print statement shows data in the array:
System.out.println(item[0]);
Any changes made within the getDetail() method, to the array, automatically appear on the original data source.

Updating array elements of Array in ArrayList

In my code below, I am storing current array in ArrayList of Arrays and whatever change I make on current array are reflected back in ArrayList at the same time? how is this happening ? But in else block, when I intialize current array with another array, it doesn't change in ArrayList.
List<int[]> res=new ArrayList<>();
int[] current=intervals[0];
res.add(current);
for(int[] interval:intervals){
int first=current[0];
int second=current[1];
int third=interval[0];
int fourth=interval[1];
if(second>=third){
current[1]=Math.max(second,fourth);
}
else{
current=interval;
res.add(current);
}
}
You have to take in account that by assigning intervals[0] to int[] current, you are not actually creating a new object. So your field current points to same object as intervals[0]. So when you call res.add(current), you are actually adding the array stored in intervals[0] to the List and any changes made in the current field will also be done in the array added to the List (because it is the same object). And as far as the code tells, you are not doing any changes on the array in else block, that's maybe why no changes are visible :P. If you do not want the array changes to be reflected in the list, before adding the array to the list, create a new array object and initialize it for example this way:
int[] current = new int[intervals[0].length]
for(int i = 0; i < intervals[0].length; ++i)
current[i] = intervals[0][i]
For your second question, if you have your array initialized like this:
int[][] intervals = new int[size][];
for(int i = 0; i < size; ++i)
intervals[i] = new int[size2];
that means that you created a new array (new object) inside each cell of the array. Now. This code:
int[] current=intervals[0];
Makes your variable current to point on the same object as intervals[0] does. So when you call res.add(current); you add the object current is pointing to to the list. So any changes made on current, or intervals[0] will also be reflected in the object stored in the list because it is the same object. But when you then assign another object to the current, when you call current = interval; you are just saying, that current now points to same object as interval does. That does not change the attributes of the original object current was pointing to (intervals[0]), current will be just pointing to another object.
A complete example of your program could help to answer to second part of your question. The central point is the pointer reference, and the resign of current has an impact to the second part of your question.
The array is a pointer to the memory where the "integers are located". At first when you add the intervals[0] into the res list, actually you are inserting a pointer address to the same memory. When you switch/change the values to the current they're reflected to res, because they points to the same memory. You can think at current[1]=Math.max(second,fourth); as: Get the address memory of the array and change its value at position 1. At this point the previous value in res in updated, because the address is the same. You can think it like an alias, they act like streets that goes to the same target.

Sorting an object array into another array based on a variable

I have a problem with a program I'm writing for a school assignment.
Essentially, before this piece of code, I already recieve and work with a bunch of information that I store into an array of objects. Now I have to sort this array (after it's sorted, I will have to calculate some things in the order of the PRIORITY variable).
presume I already have a MyClass[] array called input, that stores a finite amount of MyClass objects.
MyClass[] priorityArray = new MyClass[input.length];
for (int i=0; i<priorityArray.length; i++) {
int maxIndex = 0;
int maxPrivilege = input[i].returnPrivilege();
for (int j=1; j<input.legnth; j++) {
int currentPrivilege = input[j].returnPrivilege();
if (currentPrivilege > maxPrivilege) {
maxPrivilege = currentPrivilege;
maxIndex = j;
}
}
priorityArray[i] = input[maxIndex];
input[maxIndex].setPrivilege(-900000000);
}
the MyClass class if nothing fancy, but of course, contains a proper constructor, getter and setter methods and an integer variable "privilege".
I'm getting an error in my final tests of the program and, seeing as the program returns privileges as "-900000000", it has to have something to do with this part of the code.
It's also not even writing certain MyClass instances from the input array into the priorityArray array.
How can I clead this up? Help.
I'll rewrite my answer totally.
In this line
priorityArray[i] = input[maxIndex];
You are assigning object from one array to another array by reference. It means that there is only one object and you set value to -9000000 in the next line to it. Of course element in priorityArray will have the same changes. To fix it you need to clone your object here.

how can i initialize my array when i cant initialize as null?

i have an array of strings which i want to convert to int, pretty simple and straightforward here is the code :
public static void main(String[] args) {
String myarray[]=readfile("[pathtothefile]");
int mynums[] = new int[myarray.length];
for (int i=0;i<myarray.length;i++){
mynums[i]=Integer.parseInt(myarray[i]);
}
System.out.print(Arrays.toString(mynums));
}
But the Problem here is, if i initialize "mynums" like this: mynums[]=null; i get NullPointerException on the following line:
"mynums[i]=Integer.parseInt(myarray[i]);"
what i have to do to solve it is
int mynums[] = new int[myarray.length];
here someone explained why it happens but i dont know how to initialize now! i mean sometimes i dont know how big my array can get and i just want to initialize it. is it even possible?
In Java everything is a pointer behind the scenes. So when you do mynums[]=null, you are pointing to a null. So what is null[i]? That is where your NPE comes from. Alternatively when you point it to an array, then you are actually accessing the i'th element of the array.
You have to first initialize the array because it allocates memory depending on the array size. When you want to add for example an integer to an array it writes the int into previously allocated memory.
The memory size won't grow bigger as you add more items.( Unless you use Lists or Hashmaps, ... but it's not true for generic arrays)
If you don't know how big your array will be, consider using SparseIntArray. which is like Lists and will grow bigger as you add items.
Briefly, in java an array is an object, thus you need to treat it like an object and initialize it prior to doing anything with it.
Here's an idea. When you're initializing something as null, you're simply declaring that it exists. For example ... if I told you that there is a dog, but I told you nothing about it ... I didn't tell you where it was, how tall it was, how old, male/female, etc ... I told you none of its properties or how to access it, and all I told you was that there IS a dog (whose name is Array, for sake of argument), then that would be all you know. There's a dog whose name is Array and that is it.
Typically, arrays are used when the size is already known and generally the data is meant to be immutable. For data that are meant to be changed, you should use things like ArrayList. These are intended to be changed at will; you can add/remove elements at a whim. For more information about ArrayList, read up on the links posted above.
Now, as for your code:
public static void main(String[] args) {
ArrayList<int> myInts = new ArrayList<int>();
// define a new null arraylist of integers.
// I'm going to assume that readfile() is a way for you get the file
// into myarray. I'm not quite sure why you would need the [], but I'll
// leave it.
String myarray[] = readfile("[pathtothefile]");
for (int i = 0; i < myarray.length; i++) {
//adds the value you've specifed as an integer to the arraylist.
myInts.add(Integer.parseInt(myarray[i]));
}
for (int i = 0; i < myInts.size(); i++) {
//print the integers
System.out.print(Integer.toString(myInts.get(i)));
}
}
What if you don't use an array but an ArrayList? It grows dynamically as you add elements.

Working with an Array of Objects

#edit IT works, thanks for the answers:) I guess my bad was when I thought that
WORLD[i]=global.Values.CHUNKPATTERN();
simply takes the object on the right, clones its value('s), and assigns them to part on the left, while it turns out that it establishes a reference between two. Thanks again:)
I have simple begginer/newbie array problem:
for(int i=0; i<global.Values.WORLDVOLUME(); i++)
// global.Values.WORLDVOLUME() --> const, int. always the same.
{
WORLD[i]=global.Values.CHUNKPATTERN(); //to pre-define as 'zero only' object. Always the same. Const.
WORLD[i].chunknr=i+1;
}
System.out.println(WORLD[4].chunknr);
Of course I want WORLD[0] to have chunknr 1, WORLD[4] to have chunknr of 5 and so on.
Instead WORLD[i].chunknr=i+1; seems to update chunknr of ALL elements(not only WORLD[i]).
So that it looks like WORLD[0].chunknr = WORLD[1].chunknr=global.Values.WORLDVOLUME() here.
Anyone knows how to bypass that? I belive there's a simply solution...
Do I understand the array of objects correctly?
You can Have like(providing you have the class and constructor)
Point POINTARRAY[]= new Point[10];
POINTARRAY[1].x=5
POINTARRAY[1].y=6
POINTARRAY[3].x=17
POINTARRAY[3].y=1
Right?
How to assign that via loop?
Instead WORLD[i].chunknr=i+1; seems to update chunknr of ALL elements.
Are WORLD[0] and WORLD[1] different objects? They are not different if `WORLD[0] == WORLD[1] evaluates to true.
You have:
WORLD[i]=global.Values.CHUNKPATTERN();
Does CHUNKPATTERN create a new object every time it is called?
I bet this method
WORLD[i]=global.Values.CHUNKPATTERN();
always returns the same instance of an object so you have a reference to the same object in every slot of your array.
Subsequently
WORLD[i].chunknr=i+1;
you change the attribute chunknr of the same object in every iteration. You say
...seems to update chunknr of ALL elements
kind of true, because all elements reference the same instance.
You need to find a way to have global.Values.CHUNKPATTERN(); return a new object every time.
This line is your problem:
WORLD[i]=global.Values.CHUNKPATTERN();
This is assigning WORLD[i] a reference to global.Values.CHUNKPATTERN(), meaning that they both point to the same object! And for each iteration of your loop you are just creating more and more references to the same global object.
Sometimes this isn't what you want. In this case you need to copy the value, which can be done in a number of ways, but in most cases you can simple clone it. All Java objects support a clone() method, although sometimes you need to override it to do the correct thing for your class.
All this means is that you should replace the above line with:
WORLD[i]=(YourType)global.Values.CHUNKPATTERN().clone();
where YourType is the actual type of the class, since you omitted that from the code snippet you posted.
Hope that helps!
I guess the following line returns always the same reference:
global.Values.CHUNKPATTERN();
so the different array indices are actually point to the same referece. It's only a guess because you didn't tell us how the above function works.
Here's an example of what different array element could point to the same instace:
public class AClass{
public int val = 0;
}
AClass[] array = new AClass[2];
AClass classInstance = new AClass();
array[0] = classInstance;
array[1] = classInstance;
The code above instatiated a single AClass object (classInstance), but use 2 different array elements to reference the same instance:
System.out.println("array 1 value " + array[1].val ); // both element initialized to 0 so it prints 0
array[0].val = 15; // actually is classInstance.val to be modified, through the reference to it stored inside the first element of the array.
System.out.println("array 1 value " + array[1].val ); // print 15
For what concern the POINT example, you can use for loop this way:
Point POINTARRAY[]= new Point[10];
for(int i = 0 ; i < POINTARRAY.length; ++i)
{
POINTARRAY[1].x=...;
POINTARRAY[1].y=...;
}

Categories