Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ArrayList modifying value returned by "get" method [duplicate]

I have below two situations related to ArrayList get method, one with custom class and one with String class:

1. Below is the example of modifying Custom class ArrayList element:

ArrayList<MyClass> mTmpArray1 = new ArrayList<MyClass>();
MyClass myObj1 = new MyClass(10);  
mTmpArray1.add(myObj1);

MyClass myObj2 = mTmpArray1.get(0);  
myObj2.myInt = 20;

MyClass myObj3 = mTmpArray1.get(0);  
Log.d(TAG, "Int Value:"+myObj3.myInt);    // Prints "20" 

2. And below is the example of modifying String ArrayList element:

ArrayList<String> mTmpArray2 = new ArrayList<String>();  
mTmpArray2.add("Test_10");

String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";

String myStr2 = mTmpArray2.get(0);
Log.d(TAG, "Str Value:"+myStr2);  // Prints "Test_10" 

So in case of MyClass ArrayList, when I call get and modify the value, then I see change is reflecting when I do get again.

But same way when I modify String ArrayList, then changes are not reflecting.

What is the different in of the get method in both the scenarios?
Is it that in case of String, String class creating deep copy and returns new object, and in case of Custom class shallow copy is created?

In the first scenario applicable to "LinkedHashMap", "HashMap" and "List"?

like image 759
User7723337 Avatar asked Mar 18 '15 09:03

User7723337


People also ask

Can ArrayList store duplicate?

An ArrayList does not check for duplicates, you could stuff the same object in there over and over again.

How do you find if ArrayList contains duplicates or not?

One more way to detect duplication in the java array is adding every element of the array into HashSet which is a Set implementation. Since the add(Object obj) method of Set returns false if Set already contains an element to be added, it can be used to find out if the array contains duplicates in Java or not.

Does ArrayList remove duplicates?

Duplicate items can be removed from the ArrayList by using a HashSet as duplicate items are not allowed in a HashSet. So the ArrayList is converted into a HashSet and that removes the duplicate items. Then the HashSet is converted back into an ArrayList.


3 Answers

Your are not doing the same thing in the two cases.

Here you update the state of an object, so the change affects the object stored in the list :

myObj2.myInt = 20;

Here you are assigning a new object to a local variable, so the list is not affected :

myStr1 = "Test_20";

If String was mutable, you could have modified the String by calling some method, and the change would have been reflected in the object stored in the list :

myStr1.setSomething(...);

On the other hand, if in the first case you would have changed the value of the local variable, the object stored in the list wouldn't have been affected :

myObj2 = new MyClass (...);
like image 86
Eran Avatar answered Sep 22 '22 23:09

Eran


Strings are immutable. You're not inserting the new string into the array list.

When you do String myStr2 = mTmpArray2.get(0);, even tho you are pointing to a reference in the ArrayList, any attempt to change the value, will (because of String immutability) create a new String (myStr2) that will not reference the ArrayList anymore.

When you do myStr1 = "xxx", you're not actually changing the ArrayList reference, you're changing a new (copy) (now called myStr1) that was grabbed from the ArrayList and it has a local scope.

Read some more about Strings: Immutability of Strings in Java

Now in the first example, you are pointing to a mutable object (your custom class) so you're literally changing the direct value, through the reference. Welcome to Java. ;)

Unrelated: This code: MyClass myObj1 = new MyClass(10); is (arguably) considered bad. It's better to use a factory pattern that is a lot easier to read. In other words, public constructors with parameters are hard to read (for example, I have no idea what I am constructing when I read your code).

A (perhaps) better approach would be: MyClass myObj = MyClass.createInstanceWithCapacity(10); // i've invented the name because I don't know what your 10 is, but look at both, which one do you think is easier to understand upon first glance?

Disclaimer: The above unrelated comment is my personal opinion and not all developers will agree. ;)

like image 20
Martin Marconcini Avatar answered Sep 21 '22 23:09

Martin Marconcini


Strings have very nice property called "Immutablity"

This means that String cannot be mutable (changed), when we create/ try to refer to old string, a new instance string is created. And any changes we do are saved in new instance and it do not affect the old string

For example,

String s = "Old String";
System.out.println("Old String : "+s); // output : Old String

String s2 = s;
s2 = s2.concat(" made New");
System.out.println("New String : "+s2); // output : Old String made New
System.out.println("Old String is not changed : "+s); // output : Old String
like image 27
Kushal Avatar answered Sep 24 '22 23:09

Kushal