Updating array elements of Array in ArrayList - java

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.

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.

Changing value in one array changes value in another array

I have really strange problem. In activity I declare two arrays
private String original[] = new String[100];
private String changed[] = new String[100];
Then I assign values to those two arrays in OnCreate:
Bundle extras = getIntent().getExtras();
if (extras != null) {
original = extras.getStringArray("sentArray");
changed = original;
}
Now if I change values of members of changed array, original array will also have that members changed.
For example, after I do
changed[0] = "New value";
value of original[0] is also "New value".
How is something like that possible? Is this a bug?
changed = original;
This line is setting 'changed' to 'original' so they're the same array with the same pointers. You need to copy the array instead of setting changed equal to original.
You can try using System.arraycopy()
Everything in Java are passed-by value.. In case of Array(Which is
nothing but an Object), array reference is passed by value.. (Just
like an object reference is passed by value)..
When you pass an array to other method, actually the reference to that
array is copied..
Any changes in the content of array through that reference will affect
the original array.. But changing the reference to point to a new
array will not change the existing reference in original method..
Use
System.arraycopy()
Check this
When u copy an array like this:
changed = original;
you are copying the reference of the array. if you want to copy all the values from one array to other, you can do this:
for(int i = 0; i < original.size(); i++){
changed[i] = original[i];
}
That`s one way you can do this.
Doing this, if you change anything from the first one or the second one, the other will remain untouchable.
Hope i can help.
When we do Changed = Original, we actually assigning reference of array. Hence if we make any change to one array, it would be reflected in other array as well because both Changed and Original refer to same location.
We can also use System.arraycopy() Method. System is present in java.lang package. Its signature is as :
public static void arraycopy(Object src, int srcPos, Object dest,
int destPos, int length)

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=...;
}

I need to make a copy of an array of cards, but I am only given the address of the array I need to copy

I need to make a temporary copy of an array of cards that I do not have direct access to because it is in another class named Hand. I am given a method called getHand() which returns the reference to the array I need a copy of in the class RummyHand which is a subclass of Hand. The variable rummyHand is an instance variable in the RummyHand class and is a Hand object. Also I am working in eclipse if that matters.
but neither this:
Card[] temp = new Card[8];
temp = rummyHand.getHand();
or this:
Card[] temp = rummyHand.getHand();
has copied the array like I thought it would.
You can use Arrays.copyOf or System.arrayCopy to copy an array, or, more simply, clone():
Card[] temp = rummyHand.getHand().clone();
Note that using the = operator never copies any data. All = does is make a variable refer to a different thing. This is important to understand because otherwise it will cause you a lot of trouble down the road.
In (hopefully useful) detail:
new Card[8];
creates an array: a new area of memory big enough to hold pointers to 8 cards.
Card[] temp
creates a variable that must point to some kind of array of cards. The
=
in the middle makes the variable point to that area of memory. The expression
rummyHand.getHand();
supplies you with the address of a different area of memory. So the line
temp = rummyHand.getHand();
just makes the temp variable point to that area of memory instead. copyOf, arrayCopy and clone all work by creating a new array and filling it with the references from the original array, then handing you back the new array.
use
Card[] hand = rummyHand.getHand();
Card[] temp = new Card[hand.length()];
System.arraycopy(hand,0,temp,0,hand.length());
Afterwards you have a copy of the array - but keep in mind that the references to the cards in the array are still the same. Therefore if you change a property of a card in temp it will also change the card in hand as both arrays contain the same "card instances".
You can use clone to copy an array:
Card[] temp = rummyHand.getHand().clone();
This will give you an exact copy of the same length as the original. If you want the copy eight elements long regardless of the length of the original, you can use Arrays.copyOf:
Card[] temp = Arrays.copyOf(rummyHand.getHand(), 8);
There are a few ways to copy an array. The most basic is to create an array of the same size as the source array, then loop over the elements of the source array and add each one to your new copy:
Card[] source = rummyHand.getHand();
Card[] temp = new Card[source.length];
// for loop:
for (int i = 0; i < source.length; i++)
temp[i] = source[i];
But there are java utility classes that will do this for you. See Arrays.copyOf:
Card[] temp = Arrays.copyOf(source, source.length);
But note that your new array will contain the same Card references as the source array, meaning that any changes to the objects in the array won't change copies: they'll change the actual object. If you need copies of the contents of the array, then you'll need to use the loop, and make a copy of each Card before adding it to the temp array.
When you're doing: temp = rummyHand.getHand();, you're getting a reference to the original array, not a copy, and so any changes that you make will change the array in the rummyHand object..

Make a copy of a variable and add to Arraylist

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

Categories