ArrayList<String> Object assignment - java

I have two separate objects ArrayList<String> in two separate packages Top and top10. I assign the value of top10 to Top in my activity. And now if I remove an element from Top it also gets removed from top10. I don't know why is this happening? I feel totally dumbfounded. Is there something I don't know about java? Or is it android?
This is my activity code:
ArrayList<String> Top = new ArrayList<String>();
// ServiceCall is the name of the class where top10 is initialized.
Top = ServiceCall.top10;
System.out.println("top WR: "+ServiceCall.top10);
if(Top.get(0).equals("Please Select")) Top.remove(0);
System.out.println("top WR: "+ServiceCall.top10);
The second printed out statement has one element less than the one before.

You are pointing to the same Object.
Top = ServiceCall.top10;
is not creating a new Object, but making a reference to the other one, hence all changes in both pointers will be reflected in the same Object.
You'll have to create a new one passing the other one as parameter:
List<String> Top = new ArrayList<String>(ServiceCall.top10);

You are pointing Top to top10, not creating a new list (your initializer is effectively unused right now, as you are just repointing it to the other list.)
You should do:
ArrayList<String> Top = new ArrayList<String>(ServiceCall.top10);
This will create a shallow copy.

Related

Why do "ArrayList.remove" remove both in local variable and in myApplicationClass? [duplicate]

This question already has answers here:
Why does one arraylist change when a copy of it is modified
(6 answers)
Closed 5 years ago.
I have a MyApplicationClass into which I stock An ArrayList, then I create a variable ArrayList in my MainActivity and assign it the variable in MyApplciationClass and finally I call remove to the local variable to remove a value but the value is removed from both MyApplicationClass and the localvariable and it can be possible because I just retrieve the list from MyApplicationClass I didin't make anything else ?
Here is my code:
MyApplicationClass:
private ArrayList<String> text = new ArrayList<>();
public ArrayList<String> getText() {
return text;
}
public void addTest(String input) {
text.add(input);
}
MainActivity:
//When click on a button:
final MyApplicationClass myApplicationClass = (MyApplicationClass) getApplicationContext();
//I add some example values
myApplicationClass.addTest("1");
myApplicationClass.addTest("2");
//Here I retrieve the variable in MyApplicationClass to put in into a local variable:
ArrayList<String> testlocal = myApplicationClass.getText();
//And here I remove a value from the localvariable testlocal:
test.remove(1);
But when I debug and see variable I can see that the value is correctly deleted in testlocal but too in text in MyApplicationClass but I just want to remove a value from textlocal.
Thanks a lot.
The two variables refers to the same ArrayList object.
This assignment makes testlocal refers to the ArrayList object of the MyApplicationClass instance :
ArrayList<String> testlocal = myApplicationClass.getText();
To create a new ArrayList, you have to create a new object by using the new operator :
ArrayList<String> testlocal = new ArrayList<>(myApplicationClass.getText());
Now removing (or even adding) one element in any of these two ArrayList objects will never be reflected in the other ArrayList object.
But note that new ArrayList(Collection c) will not make a deep copy of the elements copied.
So modifying the state of any element in one or the other ArrayList object will be still reflected in the other.
In your actual case, it is not a problem as the Lists store only String values that are de facto immutable.
You need to create a copy of the original list. Also, generally it's better to depend on the List interface instead of the ArrayList class.
You can create the copy in the getText() method. This is easy because you need to modify the code on only one place. On the other hand, no outer class will be able to change your MyApplicationClass:
public List<String> getText() {
return new ArrayList<>(text);
}
Alternatively, you can create a local copy whenever you retrieve it:
List<String> testlocal = new ArrayList<>(myApplicationClass.getText());

Java How to create objects of class without name

This is a pretty simple question but I was wondering about making objects of classes without names. For example, if I had a class 'Zombie' how would I create a new one without assigning a new name each time (e.g., Zombie zombie1 = new Zombie();)
new Zombie() will create a new zombie instance. You do not, however, have to assign it to a local variable or data member if you don't want to. You could, for instance, accumulate these zombies in a collection:
List<Zombie> undeadLegion = new LinkedList<>();
for (int i = 0; i < 1000; ++i) {
undeadLegion.add(new Zombie());
}
What you're referring to is name binding: the association of data with an identifier.
The most common use of binding is to determine the scope of a variable. Bound data is guaranteed by the language to exist (say "in scope"). In Java, the converse is not true: unbound data might still exist on the heap before garbage collection. However, there is no way to access this data, because you have no way to identify it (short of deep magic involving the garbage collector).
You can create unbound data just by writing new Zombie(). You do not have to give it a specific name; it could be an unnamed member of a (named) array:
// Create a new ArrayList<> and bind it to the name list.
List<Zombie> list = new ArrayList<Zombie>();
// Create new Zombie objects, but do not name them.
// Instead, add them to the list.
for (int i = 0; i < 5; ++i) {
list.add(new Zombie());
}
You can also pass an object directly to a function. It won't be bound to any names in the caller's scope, but it will be bound in the callee's scope:
void a()
{
b(new Zombie());
}
void b(Zombie z)
{
}
Here, the new Zombie() is not named in a at all -- but once it's passed to b, it is bound to z.
Finally, you can create an object and do exactly nothing with it:
new Zombie();
It will immediately be unreachable unless its constructor stores a reference to itself somewhere. However, side effects such as printing to the console will still be visible.
Objects don't have names. There is no way to assign a name to the object, nor can you find out what it was at runtime (with help from debug information)
What you may have meant, is how do I avoid declaring a named reference to an object.
The simplest way it to use the reference as an expression like
System.out.println(new Zombie());
Objects don't have names. Variables have names. You don't have to store the result of new into a variable: you can pass it directly as a parameter for example, or just throw it away.
If you want to pass a new object to a method or such, you can just use the constructor call (new Zombie()) without assigning it to a variable.
For example, if you have method called doThingsWithZombie() that takes a Zombie object, you can do the following:
doThingsWithZombie(new Zombie());
You could also add the new object to a list:
LinkedList<Zombie> zombieList = new LinkedList<Zombie>();
zombieList.add(new Zombie()); // Add a zombie
zombieList.add(new Zombie()); // Add a zombie
zombieList.get(0) // Gets the first zombie

Java class copying and arrays

I am having some issues withs objects within an array working as one object rather than seperately as intended. For example
boardArray = new object[4];
workingBoardArray = new object[4];
boardArray[0] = new board(boardA);
boardArray[1] = new board(boardB);
boardArray[2] = new board(boardC);
boardArray[3] = new board(boardD);
int selectedBoard = selectBoard(boardArray);
workingBoardArray[0] = boardArray[selectedBoard];
workingBoardArray[1] = boardArray[selectedBoard];
workingBoardArray[2] = boardArray[selectedBoard];
workingBoardArray[3] = boardArray[selectedBoard];
workingBoard[0].moveUp();
workingBoard[1].moveRight();
workingBoard[2].moveDown();
workingBoard[3].moveLeft();
This code creates a set of 4 boards, finds the desired board, copies that board into the working board array and then shifts each working board in a new direction. The problem is that the boards all act together. So if I do moveUp() on workingBoard[0], workingBoard[1] is also moved up. Is there any way around this, I feel like I am missing some fundamental understand or a really silly mistake.
I also tried using a copy constructer like
workingBoard[0] = new Board(boardArray[selectedBoard].getBoard);
Which retrieves all essential board information and creates a new board with it, but that doesnt seem to affect anything. Any help would be great
Look at this code:
int selectedBoard = selectBoard(boardArray);
workingBoardArray[0] = boardArray[selectedBoard];
workingBoardArray[1] = boardArray[selectedBoard];
workingBoardArray[2] = boardArray[selectedBoard];
workingBoardArray[3] = boardArray[selectedBoard];
That's setting all four array elements to be references to the same object. So yes, when you modify that object by calling moveUp() or whatever, that change will be visible via all the elements in the array.
It sounds like you may want to create a copy of the board each time. Depending on what your board type (which should be called Board to follow naming conventions) does, you may want to just implement Cloneable (quite possibly overriding the clone() method) or provide some other sort of copying operation.
Are you aware of the difference between a reference and an object in Java, and that the array only contains references, not objects? (Likewise any variable value will only be a reference rather than on object.) It's really important to understand how objects work in Java. For example:
StringBuilder a = new StringBuilder();
StringBuilder b = a;
a.append("Foo");
System.out.println(b); // Still prints "Foo"
Here we've got one StringBuilder object, even though there are two variables (a and b) whose values refer to that same object.
... copies that board into the working board array and then shifts each working board in a new direction.
Actually you don't copy the board. There is only one board instance which is referenced four times from workingBoardArray. To make copies of the board you have either to implement the clone method or provide a custom copy method.
For example if you implement the clone method you could write:
workingBoardArray[0] = boardArray[selectedBoard].clone();

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

Elements in java ArrayList taking up two places

I have made a LinkedList to store State objects which is a class I have created. I can add states to the list as expected, but whenever I try the size() method on the list it always returns twice the amount of elements I have added. Why is it doing this and how can I then use the get(n) method if each element has 2 values of n?
Here's the code used to create and add to the list:
static ArrayList<State> stateTable = new ArrayList<State>();
stateTable.add(new State(new Item(0,0)));
I will add that the adding to the list is done inside the constructor for State objects so that all created States get put in the stateTable.
Thanks
I will add that the adding to the list is done inside the constructor
for State objects so that all created States get put in the
stateTable.
If you already add the states to your list inside the constructor and additionally have the line
stateTable.add(
new State(new Item(0,0)) // <= first time inside new State(...)
); // <= second time explicitely in this line
then you are indeed adding it twice.
search for .add( and make sure you are not calling it in multiple places.
If your ArrayList is not marked as private mark it as private.
If you return your ArrayList from a method do return a read-only version via: Collection.unmodifiableList(stateTable);
If you load the data in one method or the constructor and do not intend to do it anywhere else than do it something like:
private static final List<State> stateTable;
static
{
final List<State> temp;
temp = new ArrayList<State>();
temp.add(new State(new Item(0,0)));
stateTable = Collections.unmodifiableList(stateTable);
}
Using the unmodifiableList will cause your program to crash if you add objects into it.

Categories