I have a list of sets of pairs. If I use equal does it copy every set over?
List<HashSet<Pair>> list1 = new ArrayList<HashSet<Pair>>();
List<HashSet<Pair>> list2 = new ArrayList<HashSet<Pair>>();
list1.add(0, new HashSet<Pair>());
list1.add(1, new HashSet<Pair>());
list1.add(2, new HashSet<Pair>());
list1.add(3, new HashSet<Pair>());
If I do list2 = list1, does it copy over perfectly? Because when I use it, it crashes.
Iterator<Pair> it1 = list2.get(0).iterator();
Iterator<Pair> it2 = list2.get(1).iterator();
Iterator<Pair> it3 = list2.get(2).iterator();
Iterator<Pair> it4 = list2.get(3).iterator();
list2 = list1
This assignment simply assigns the reference list2 to point at the same List as list1. (Note that there is only one list with two references to it.) If you want to copy the list, you need to use a copy constructor:
list2 = new ArrayList<HashSet<Pair>>(list1);
No. The assignment doesn't copy anything, and instead updates the list2 reference to point to list1. So you are able to use list2 as if it were list1; however changes you make to 2 will be reflected in 1.
Related
I am creating an ArrayList of ArrayList and adding ArrayLists to it. But everytime I make changes to the ArrayList, it is being reflected in the ArrayList<ArrayList>.
Example:
List<List<String>> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<String>();
list2.add("Cat");
list1.add(list2); //no problem
list2.clear();
list2.add("Dog");
list1.add(list2); //problem! the cat is replaced by two dogs this time!!
How do I make sure that updates to list2 is not reflected in list1?
Short answer ... replace
list2.clear();
with
list2 = new ArrayList<String>();
The problem is happening because list1.add(list2) adds a reference to list2 to list1. It is NOT making a copy of the list that list2 refers to, at any point. So you end up adding multiple references to the same list object to list1.
This is a consequence of the way that Java argument passing works, and the way that the collection APIs have all been designed to work.
What I've observed from the following equivalent but runnable program:
import java.util.List;
import java.util.ArrayList;
public class Test1 {
public static void main(String[] args){
List<ArrayList<String>> list1 = new ArrayList<ArrayList<String>>();
ArrayList<String> list2 = new ArrayList<String>();
list2.add("Cat");
System.out.println(list2);
list1.add(list2);
System.out.println(list1);
list2.clear();
System.out.println(list2);
list2.add("Dog");
System.out.println(list2);
list1.add(list2);
System.out.println(list2);
System.out.println(list1);
if(list1.get(0) == list1.get(1)) {
System.out.println("Lists at position 0 and 1 are the same");
}
}
}
it's not that "the cat is replaced by two dogs" as you wrote in a comment of your code but that, at the end, i.e. after the last statement, list1 contains two lists, each of them containing a "Dog".
This is of course due to the fact that when you add list2 to list1 the second time, you're not adding actually a new list, but the same one. You probably thought that by clearing the list2 and then adding it again would add a new list with a new item "Dog", but what you actually did was modifying the same object and adding the same reference. Remember that list2 and list1 are references!
What you need to do is create a new ArrayList object, like:
ArrayList<String> list3 = new ArrayList<String>();
list3.add("Dog");
list1.add(list3);
instead of clearing list2 and adding it again.
Check also these articles:
Why can't you have a "List<List<String>>" in Java?
Working with a List of Lists in Java
What are classes, references and objects?
I have an arraylist as below:
ArrayList<List<Double>> myAr = new ArrayList<>();
I add the value to the array as below:
myAr.add(Arrays.asList((double)3,(double)4,(double)5,(double)6));
myAr.add(Arrays.asList((double)6, (double)8, (double)1, (double)4));
Then I assign to a new arraylist and copied myAr to temp as below:
ArrayList<List<Double>> temp = new ArrayList<>();
temp = (ArrayList<List<Double>>)myAr.clone();
I did some modification to an element as below:
temp.get(0).set(2, 9.0);
Then I display the output for both temp and myAr.
System.out.println(temp);
System.out.println(myAr);
Unfortunately, both displayed the same output. I want the myAr to be remain as it is. What can I do?
Thank you
You need to implement a deep copy, i.e. you actually need to duplicate the inner lists:
ArrayList<List<Double>> temp = new ArrayList<>();
for (List<Double> list : myAr) {
temp.add(Arrays.asList(list.toArray(new Double[0]));
}
otherwise the elements of temp and myAr point to the same underlying lists.
This is happening because the ArrayList you are clonig ie myAr contains(not primitive types) .To achieve this task you have to individually copy all the elements using a for loop.
Use the following code, it will work:
ArrayList<List<Double>> myAr = new ArrayList<>();
myAr.add(Arrays.asList((double)3,(double)4,(double)5,(double)6));
myAr.add(Arrays.asList((double)6, (double)8, (double)1, (double)4));
ArrayList<List<Double>> temp = new ArrayList<>();
//copy old list to new list (deep copy)
for (List<Double> list : myAr)
{
temp.add(list);
}
//output original list
for (List<Double> list : myAr)
{
System.out.println(list);
}
System.out.println();
System.out.println("Temp array");
//editing value in new list
temp.get(0).set(2, 11.0);
//output new list
for (List<Double> list : temp)
{
System.out.println(list);
}
.clone() creates a shallow copy (i.e. it creates a new collection and copies the pointers of the values in the collection, but does not copy the values).
If you want to achieve a deep copy, use a copy constructor:
temp = new ArrayList<>(myArr);
I think doing arraylist1=arraylist2 makes the 2 of them share the same memory. How can I copy an arraylist without them doing that? I want to treat them sepparately.
List<Integer> rez = new ArrayList<>();
List<Integer> rezc = new ArrayList<>();
rez.add(1);
rezc=rez;
rezc.add(2);
for (int s : rez) {
System.out.print(s + " ");
}//this will print 1 2
I think doing arraylist1=arraylist2 makes the 2 of them share the same memory.
Not quite, it makes both of those references refer to the same, single, object.
How can I copy an arraylist without them doing that?
Lots of options:
ArrayList has a copy constructor:
List<Integer> rezc = new ArrayList<>(rez);
List has an addAll method:
List<Integer> rezc = new ArrayList<>();
rezc.addAll(rez);
ArrayList has a clone method, but it's a bit ugly to use if rez is declared as a List because you have to assume it's an ArrayList and cast it, which is probably not a great idea:
List<Integer> rezc = (List<Integer>)((ArrayList<Integer>)rez).clone();
It's well worth reading through the JavaDoc when trying to figure things like this out.
The statement arraylist1=arraylist2 means they are referring to same ArrayList object. Reference variables arraylist1 and arraylist2 are referring to same object and hence, the changes done by arraylist1 will be seen when you are trying to access the object by arraylist2
If you want to make a new ArrayList then, ArrayList rezc = new ArrayList(rez)
Instead of this line rezc=rez;
Use List<Integer> rezc = new ArrayList<>(rez);
The long hand way is a for loop to cycle though one list while adding all the items to the second. Something like
for (int I = 0; I < rez.size() I++) {
rezc.add(rez.get(I)); }
But the previous answers are much more efficient.
If I understand correctly you are talking about Java shallow cloning v/s deep cloning. In this case the below code might help
List<Integer> rez = new ArrayList<>();
List<Integer> rezc = new ArrayList<>();
rez.add(1);
rezc.addAll(rez); // addAll
List<Integer> rezc2 = (List<Integer>)((ArrayList<Integer>)rez).clone(); //clone
ArrayList<ArrayList<String>> list1 = new ArrayList<ArrayList<String>>();
ArrayList<String> list2 = new ArrayList<String>();
list2.add("foo");
System.out.println(list2); //[foo]
list1.add(list2);
System.out.println(list1); //[[foo]]
list2.set(0, "bar");
System.out.println(list2); //[bar]
System.out.println(list1); //[[bar]]
The code above shows 2 lists. When I add list2 (containing foo) to list1 they both now contain foo. But when I modify list2 to bar, list1 will change as well. I've always thought the add method only gives a copy of list2 to list1 and what I do to list2 will not change for list1.
How can I make it that I add list2 to list1 but allow list2 to be freely modified in the future so list1 will not be affected again?
In Java references are passed by value, not the object referenced. This means that list2.add(list1); cannot alter the reference list1 but it takes a reference to the same object and if you change that it is visible.
The way you should write this is
List<List<String>> list1 = new ArrayList<List<String>>();
List<String> list2 = new ArrayList<String>();
list2.add("foo");
System.out.println(list2); //[foo]
list1.add(new ArrayList<String>(list2)); // take a copy of the list.
System.out.println(list1); //[[foo]]
list2.set(0, "bar");
System.out.println(list2); //[bar]
System.out.println(list1); //[[foo]]
or
list1.add(list2);
list2 = new ArrayList<String>();
list2.add("bar");
System.out.println(list2); //[bar]
System.out.println(list1); //[[foo]]
My example above is simple but my actual problem is buried in nested loops and such.
List<List<String>> list1 = new ArrayList<List<String>>();
for(some loop) {
List<String> list2 = new ArrayList<String>();
// populate list2, can be smaller than the previous list2 !!
list1.add(list2);
}
How about list1.add(list2.clone()); ?
This will create a copy of list2 (allocate memory, clone contents etc) and put reference to it in list1.
You should clone every item and add to a new list.
I have some data structures, and I would like to use one as a temporary, and another as not temporary.
ArrayList<Object> myObject = new ArrayList<Object>();
ArrayList<Object> myTempObject = new ArrayList<Object>();
//fill myTempObject here
....
//make myObject contain the same values as myTempObject
myObject = myTempObject;
//free up memory by clearing myTempObject
myTempObject.clear();
now the problem with this of course is that myObject is really just pointing to myTempObject, and so once myTempObject is cleared, so is myObject.
How do I retain the values from myTempObject in myObject using java?
You can use such trick:
myObject = new ArrayList<Object>(myTempObject);
or use
myObject = (ArrayList<Object>)myTempObject.clone();
You can get some information about clone() method here
But you should remember, that all these ways will give you a copy of your List, not all of its elements. So if you change one of the elements in your copied List, it will also be changed in your original List.
originalArrayList.addAll(copyArrayList);
Please Note: When using the addAll() method to copy, the contents of both the array lists (originalArrayList and copyArrayList) refer to the same objects or contents. So if you modify any one of them the other will also reflect the same change.
If you don't wan't this then you need to copy each element from the originalArrayList to the copyArrayList, like using a for or while loop.
There are no implicit copies made in java via the assignment operator. Variables contain a reference value (pointer) and when you use = you're only coping that value.
In order to preserve the contents of myTempObject you would need to make a copy of it.
This can be done by creating a new ArrayList using the constructor that takes another ArrayList:
ArrayList<Object> myObject = new ArrayList<Object>(myTempObject);
Edit: As Bohemian points out in the comments below, is this what you're asking? By doing the above, both ArrayLists (myTempObject and myObject) would contain references to the same objects. If you actually want a new list that contains new copies of the objects contained in myTempObject then you would need to make a copy of each individual object in the original ArrayList
Came across this while facing the same issue myself.
Saying arraylist1 = arraylist2 sets them both to point at the same place so if you alter either the data alters and thus both lists always stay the same.
To copy values into an independent list I just used foreach to copy the contents:
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
fill list1 in whatever way you currently are.
foreach(<type> obj in list1)
{
list2.Add(obj);
}
Supopose you want to copy oldList into a new ArrayList object called newList
ArrayList<Object> newList = new ArrayList<>() ;
for (int i = 0 ; i<oldList.size();i++){
newList.add(oldList.get(i)) ;
}
These two lists are indepedant, changes to one are not reflected to the other one.
Lets try the example
ArrayList<String> firstArrayList = new ArrayList<>();
firstArrayList.add("One");
firstArrayList.add("Two");
firstArrayList.add("Three");
firstArrayList.add("Four");
firstArrayList.add("Five");
firstArrayList.add("Six");
//copy array list content into another array list
ArrayList<String> secondArrayList=new ArrayList<>();
secondArrayList.addAll(firstArrayList);
//print all the content of array list
Iterator itr = secondArrayList.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
In print output as below
One
Two
Three
Four
Five
Six
We can also do by using clone() method for which is used to create exact copy
for that try you can try as like
**ArrayList<String>secondArrayList = (ArrayList<String>) firstArrayList.clone();**
And then print by using iterator
**Iterator itr = secondArrayList.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}**
You need to clone() the individual object. Constructor and other methods perform shallow copy. You may try Collections.copy method.
Straightforward way to make deep copy of original list is to add all element from one list to another list.
ArrayList<Object> originalList = new ArrayList<Object>();
ArrayList<Object> duplicateList = new ArrayList<Object>();
for(Object o : originalList) {
duplicateList.add(o);
}
Now If you make any changes to originalList it will not impact duplicateList.
to copy one list into the other list, u can use the method called
Collection.copy(myObject myTempObject).now after executing these line of code u can see all the list values in the myObject.
Copy of one list into second is quite simple , you can do that as below:-
ArrayList<List1> list1= new ArrayList<>();
ArrayList<List1> list2= new ArrayList<>();
//this will your copy your list1 into list2
list2.addAll(list1);
Here is a workaround to copy all the objects from one arrayList to another:
ArrayList<Object> myObject = new ArrayList<Object>();
ArrayList<Object> myTempObject = new ArrayList<Object>();
myObject.addAll(myTempObject.subList(0, myTempObject.size()));
subList is intended to return a List with a range of data. so you can copy the whole arrayList or part of it.
Suppose you have two arraylist of String type .
Like
ArrayList<String> firstArrayList ;//This array list is not having any data.
ArrayList<String> secondArrayList = new ArrayList<>();//Having some data.
Now we have to copy the data of second array to first arraylist like this,
firstArrayList = new ArrayList<>(secondArrayList );
Done!!
The simplest way is:
ArrayList<Object> myObject = new ArrayList<Object>();
// fill up data here
ArrayList<Object> myTempObject = new ArrayList(myObject);