How should I go about cloning a nest ArrayList? - java

I need to write out a method to clone a nested ArrayList.
The nested ArrayList looks like this:
ArrayList<ArrayList<Ship>> theSea = new ArrayList<ArrayList<Ship>>();
I want to copy it to a clone:
ArrayList<ArrayList<Ship>> seaClone = new ArrayList<ArrayList<Ship>>();
I've tried iterating it and copying over the lists:
for(int i = 0; i < theSea.size(); i++){
seaClone.add(theSea.get(i));
}
However, this doesn't clone the elements of the nested ArrayList<Ship> and instead just copies over a reference to it.
How should I go about cloning the elements of the nested ArrayList<Ship>?

However, this doesn't clone the elements of the nested ArrayList
and instead just copies over a reference to it.
Because it is actually what you are doing : you add the reference of the existing objects in the new List.
So instead of, create a new nested ArrayList for each cloned sublist and create new Ship objects as you add elements in the new Lists.
You could define a copy constructor in Ship for example :
public Ship(Ship model){
foo = model.foo;
bar = model.bar;
}
You can so write :
for(List<Ship> list : theSea){
List<Ship> currentList = new ArrayList<>();
for(Ship ship : list){
currentList.add(new Ship(ship));
}
clone.add(currentList);
}

Assuming Ship objects are cloneable:
List<List<Ship>> clone = theSea.stream()
.map(l -> l.stream().map(s -> (Ship)s.clone()).collect(toList()))
.collect(toList());

Something like:
ArrayList<ArrayList<Ship>> listCopy = new ArrayList<>();
for (int i=0; i<list.size(); i++) {
ArrayList<Ship> newList = new ArrayList<>();
for (int j=0; j<list.get(i).size(); j++) {
newList.add(new Ship(list.get(i).get(j)));
}
listCopy.add(newList);
}
Observe this line: newList.add(new Ship(list.get(i).get(j)));
Where you need to pass the object to the constructor and from there duplicate all the attributes, otherwise you will just create a reference to the same class.
If your ship class is to complex with many other objects inside this task may be difficult and you can use a tool like serializing to json and then revert back to object or using a java deep object cloner.

Related

Java Collections HashMap, value changes unexpectedly

public class ListMap {
HashMap<Integer, List> mp = new HashMap();
List myList = new ArrayList();
Integer x = 0;
Integer y = 5;
void test() {
for(Integer i = 0; i < 5; i++) {
x = y;
myList.add("check-1a" + i);
myList.add("check-1a" + i + 1);
y = null;
System.out.println(x); // output=5
mp.put(i, myList);
myList.clear();
}
}
1) But after clearing the List with myList.clear() the values that was inside the Map also gets cleared.
I mean to say that the map key remains there but it contains an "empty" List
2) However regarding the Objects x & y, after setting y to null how come x doesn't change?
When you add an object to a map (or any other collection), you are adding a reference to that object, not a copy. When you then make changes to the object, these changes will also affect the references in the map.
When you want to store a copy of your list, you need to create a new one. This can be done like this:
mp.put(i, new ArrayList(myList));
An alternative (and in my opinion even better) solution would be to reinitialize myList in the beginning of each loop iteration by setting it to a fresh list object:
myList = new ArrayList();
myList.add("check-1a"+i);
myList.add("check-1a"+i+1);
mp.put(i,myList);
Note that the list doesn't get destroyed when you reinitialize the variable myList. You can think of the object living on inside the map*.
*although a more technically accurate description would be "the object lives on in memory and isn't garbage-collected as long as there is still a reference to it stored in the map"
You're adding the same list to the Map multiple times and clearing it each time, so no surprise that its empty. Solution: Don't clear the list, create a new one within the for loop. This way, the Map will hold a unique List for each Integer.
public class ListMap {
HashMap<Integer,List<String>> mp=new HashMap<>();
// List<String> myList=new ArrayList<String>(); // **** get rid of
Integer x=0;
Integer y=5;
void test(){
for(Integer i=0;i<5;i++){
List<String> myList=new ArrayList<String>(); // ****** here
x=y;
myList.add("check-1a"+i);
myList.add("check-1a"+i+1);
y=null;
System.out.println(x);//output=5
mp.put(i,myList);
// myList.clear(); // **** get rid of
}
}
Also as per Tom, don't use raw types if possible, and so declare your lists as List<String> and ArrayList<String>.

go through an array of linked lists

I want to create an array of pointers to linked lists and then go through each list. To create it can I simply create however many lists I need and then just do something like
LinkedList array[] = new LinkedList[length];
and then just set a loop to set each value in the array to point to one of the lists?
How would I go through each list after I set it all up? I thought it was something like
while(array[x].hasNext()){
//do stuff
x++;
}
your while loop is incorrect:
Just do something like this!
for (LinkedList list : array) {
for (Item object : list) {
// Do something here with the item
}
}
btw you should not use LinkedList without a type, use one of the following
LinkedList<String> or
LinkedList<WhateverObjectYouLike> or
LinkedList<? extends whatEverObjectYouLike>
so lets say you want to create an array of 10 lists and every list should contain strings.
LinkedList<String> array[] = new LinkedList<String>[10];
for (int i=0; i<10; i++) {
array[i] = new LinkedList<String>();
}
// Add some strings to each list, as you like
...
// Print all added Strings:
for (LinkedList<String> list : array) {
for (String item : list) {
System.out.println(item);
}
}
You have mixed up Java array objects and the collection framework's List api. You can do what you want in a couple of ways:
Using arrays (highly discouraged—see this thread):
LinkedList array[] = new LinkedList[length];
...
for (int i = 0; i < array.length; ++i) {
LinkedList list = array[i];
// do stuff with list
}
Using a List:
List<LinkedList> array = new ArrayList<LinkedList>();
...
for (Iterator<LinkedList> iter = array.iterator();
iter.hasNext();
)
{
LinkedList list = iter.next();
// do stuff with list
}
In both cases, you might benefit from using an enhanced for loop:
for (LinkedList list : array) {
// do stuff with list
}
This works for either the array-based or List-based versions.
P.S. You should not be using raw LinkedList types. Instead, you should bind the generic type parameter of LinkedList to a specific element type (even if it's Object). For example:
List<LinkedList<String>> array = new ArrayList<LinkedList<String>>();
The language allows raw types for the sake of old code, but new code should never use them. However, the first option above will not work—you will have to use the second approach.

"Copy" nested array list

I have a nested ArrayList of the form
ArrayList<ArrayList<PointF>> nestedArraylist
I want to create a "copy" nestedArraylistCopy of nestedArraylist in the following sense:
The elements of nestedArraylistCopyshould be independent copies of the elements in nestedArraylist, i.e. should be ArrayLists holding the references to the same PointF objects in the original nestedArraylist.
Can I somehow use Collections.copy(dest, src) to do what I want? The documentation is not exactly detailed unfortunately...
Does the following code do what I want?
for(int i = 0; i < nestedArraylist.size(); i++)
nestedArraylistCopy.add(new ArrayList<PointF>(nestedArraylist.get(i)));
Is there a more efficient and or elegant solution?
Q1: after you Collections.copy, your new List object will contain the same elements as src (assuming the size is the same) which means, it holds same ArrayList<PointF> objects, hence the PointF objects are the same too. If you cannot get the info you want from the api java doc, read the source codes.
Q2: What you did is different from Collections.copy, since your copied arrayList has new Arraylist<PointF> as elements, but they contain the same elements (PointF) as the source list.
Q3: I don't know. because I don't know what do you want to have eventually. All new objects? Only ArrayList should be new objects, or all references?
According to my knowledge your solutions will update only references, as does Collection.copy(). You can use the below method, which I prefer:
List<ArrayList<PointF>> newList = new ArrayList<ArrayList<PointF>>(oldList);
A change of the old list would not affected to new list.
I tested your second option and it also has the property that changes to the old one will not affect the new List.
Note - These will also update only the references. If you change elements in your new list it will update old list too. I think Your second array will create brand new objects, but I am not 100% sure about that. I am adding my testing code below for you reference.
package test;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Lasitha Benaragama on 4/28/14.
*/
public class StckTest {
public static void main(String[] args) {
List<String> oldList = new ArrayList<String>();
oldList.add("AAAAA");
oldList.add("BBBBB");
oldList.add("CCCCC");
oldList.add("DDDDDD");
oldList.add("EEEEEE");
StckTest test = new StckTest();
List<String> newListCopy = new ArrayList<String>(oldList);
List<String> newListClone = new ArrayList<String>();
for(int i = 0; i < oldList.size(); i++)
newListClone.add(oldList.get(i));
test.printArray(newListCopy);
test.changeList(oldList);
test.printArray(oldList);
test.printArray(newListCopy);
test.printArray(newListClone);
}
public void changeList(List<String> oldList) {
oldList.remove(2);
oldList.add("FFFFF");
}
public void printArray(List<String> oldList){
for(int i = 0; i < oldList.size(); i++){
System.out.print(oldList.get(i)+",");
}
System.out.println();
}
}
You can use the clone() method to make a shallow copy of your object.
ArrayList<ArrayList<String>> nestedArraylist=new ArrayList<ArrayList<String>>();
ArrayList<String> x=new ArrayList<String>();
x.add("Deepak");
nestedArraylist.add(x);
System.out.println(nestedArraylist);
ArrayList<ArrayList<String>> nestedArraylistcopy=(ArrayList<ArrayList<String>>)nestedArraylist.clone();
System.out.println(nestedArraylistcopy);

How to copy java.util.list Collection

I am implementing a Java class responsible for ordering java.util.List. The problem comes when I use this class. I'm able to ordering the list but I want to copy the "original" list without modification so that I could register every change made on the original list. The sorted list contains object and one of its fields stores a classification id, and this id it is updated with the index value of the list.
I tried to use clone method and it keeps the list unsorted but the changes made on original list are updated in the clone list too.
Is there any way to accomplish it?
My Code:
List<Torero> listaTorero = tbTlgTorerolHome.findByExample(new Torero());
List<Torero> listaToreroTemp = ((List<Torero>) ((ArrayList<Torero>) listaTorero).clone());
Clasificacion clasificacion = new Clasificacion();
Iterator<Torero> iterTorero = clasificacion.getClasificacion(listaTorero, torero).iterator(); //Sorting List
A Clasificacion method:
public List<Torero> getClasificacion(List<Torero> listaToreroTemp, Torero torero)
{
List<Torero> listaTorero = new ArrayList<Torero>();
Collections.sort(listaToreroTemp,new ToreroClasifiacionComparator());
Iterator<Torero> iterTorero = listaToreroTemp.iterator();
int index=1;
while(iterTorero.hasNext())
{
Torero toreroTemp = iterTorero.next();
toreroTemp.setNumClasificacion(index);
listaTorero.add(toreroTemp);
index=index+1;
}
return listaTorero;
}
You may create a new list with an input of a previous list like so:
List one = new ArrayList()
//... add data, sort, etc
List two = new ArrayList(one);
This will allow you to modify the order or what elemtents are contained independent of the first list.
Keep in mind that the two lists will contain the same objects though, so if you modify an object in List two, the same object will be modified in list one.
example:
MyObject value1 = one.get(0);
MyObject value2 = two.get(0);
value1 == value2 //true
value1.setName("hello");
value2.getName(); //returns "hello"
Edit
To avoid this you need a deep copy of each element in the list like so:
List<Torero> one = new ArrayList<Torero>();
//add elements
List<Torero> two = new Arraylist<Torero>();
for(Torero t : one){
Torero copy = deepCopy(t);
two.add(copy);
}
with copy like the following:
public Torero deepCopy(Torero input){
Torero copy = new Torero();
copy.setValue(input.getValue());//.. copy primitives, deep copy objects again
return copy;
}
Use the ArrayList copy constructor, then sort that.
List oldList;
List newList = new ArrayList(oldList);
Collections.sort(newList);
After making the copy, any changes to newList do not affect oldList.
Note however that only the references are copied, so the two lists share the same objects, so changes made to elements of one list affect the elements of the other.

How can I create an Array of ArrayLists?

I am wanting to create an array of arraylist like below:
ArrayList<Individual>[] group = new ArrayList<Individual>()[4];
But it's not compiling. How can I do this?
As per Oracle Documentation:
"You cannot create arrays of parameterized types"
Instead, you could do:
ArrayList<ArrayList<Individual>> group = new ArrayList<ArrayList<Individual>>(4);
As suggested by Tom Hawting - tackline, it is even better to do:
List<List<Individual>> group = new ArrayList<List<Individual>>(4);
As the others have mentioned it's probably better to use another List to store the ArrayList in but if you have to use an array:
ArrayList<Individual>[] group = (ArrayList<Individual>[]) new ArrayList[4];
You will need to suppress the warning but it's safe in this case.
This works:
ArrayList<String>[] group = new ArrayList[4];
Though it will produce a warning that you may want to suppress.
You can create a class extending ArrayList
class IndividualList extends ArrayList<Individual> {
}
and then create the array
IndividualList[] group = new IndividualList[10];
You can create Array of ArrayList
List<Integer>[] outer = new List[number];
for (int i = 0; i < number; i++) {
outer[i] = new ArrayList<>();
}
This will be helpful in scenarios like this. You know the size of the outer one. But the size of inner ones varies. Here you can create an array of fixed length which contains size-varying Array lists. Hope this will be helpful for you.
In Java 8 and above you can do it in a much better way.
List<Integer>[] outer = new List[number];
Arrays.setAll(outer, element -> new ArrayList<>());
This works, array of ArrayList. Give it a try to understand how it works.
import java.util.*;
public class ArrayOfArrayList {
public static void main(String[] args) {
// Put the length of the array you need
ArrayList<String>[] group = new ArrayList[15];
for (int x = 0; x < group.length; x++) {
group[x] = new ArrayList<>();
}
//Add some thing to first array
group[0].add("Some");
group[0].add("Code");
//Add some thing to Secondarray
group[1].add("In here");
//Try to output 'em
System.out.println(group[0]);
System.out.println(group[1]);
}
}
Credits to Kelvincer for some of codes.
The problem with this situation is by using a arraylist you get a time complexity of o(n) for adding at a specific position. If you use an array you create a memory location by declaring your array therefore it is constant
You can't create array of generic type. Create List of ArrayLists :
List<ArrayList<Individual>> group = new ArrayList<ArrayList<Individual>>();
or if you REALLY need array (WARNING: bad design!):
ArrayList[] group = new ArrayList[4];
Creation and initialization
Object[] yourArray = new Object[ARRAY_LENGTH];
Write access
yourArray[i]= someArrayList;
to access elements of internal ArrayList:
((ArrayList<YourType>) yourArray[i]).add(elementOfYourType); //or other method
Read access
to read array element i as an ArrayList use type casting:
someElement= (ArrayList<YourType>) yourArray[i];
for array element i: to read ArrayList element at index j
arrayListElement= ((ArrayList<YourType>) yourArray[i]).get(j);
List[] listArr = new ArrayList[4];
Above line gives warning , but it works (i.e it creates Array of ArrayList)
To declare an array of ArrayLists statically for, say, sprite positions as Points:
ArrayList<Point>[] positionList = new ArrayList[2];
public Main(---) {
positionList[0] = new ArrayList<Point>(); // Important, or you will get a NullPointerException at runtime
positionList[1] = new ArrayList<Point>();
}
dynamically:
ArrayList<Point>[] positionList;
int numberOfLists;
public Main(---) {
numberOfLists = 2;
positionList = new ArrayList[numberOfLists];
for(int i = 0; i < numberOfLists; i++) {
positionList[i] = new ArrayList<Point>();
}
}
Despite the cautions and some complex suggestions here, I have found an array of ArrayLists to be an elegant solution to represent related ArrayLists of the same type.
ArrayList<String>[] lists = (ArrayList<String>[])new ArrayList[10];
You can create like this
ArrayList<Individual>[] group = (ArrayList<Individual>[])new ArrayList[4];
You have to create array of non generic type and then cast it into generic one.
ArrayList<Integer>[] graph = new ArrayList[numCourses]
It works.
I think I'm quite late but I ran into the same problem and had to create an array of arraylists as requested by my project in order to store objects of different subclasses in the same place and here is what I ended up doing:
ArrayList<?>[] items = new ArrayList[4];
ArrayList<Chocolate> choc = new ArrayList<>();
ArrayList<Chips> chips = new ArrayList<>();
ArrayList<Water> water = new ArrayList<>();
ArrayList<SoftDrink> sd = new ArrayList<>();
since each arraylist in the array would contain different objects (Chocolate , Chips , Water and SoftDrink )
--it is a project to simulate a vending machine--.
I then assigned each of the Arraylists to an index of the array:
items[0]=choc;
items[1]=chips;
items[2]=water;
items[3]=sd;
Hope that helps if anyone runs into a similar issue.
I find this easier to use...
static ArrayList<Individual> group[];
......
void initializeGroup(int size)
{
group=new ArrayList[size];
for(int i=0;i<size;i++)
{
group[i]=new ArrayList<Individual>();
}
You can do thi. Create an Array of type ArrayList
ArrayList<Integer>[] a = new ArrayList[n];
For each element in array make an ArrayList
for(int i = 0; i < n; i++){
a[i] = new ArrayList<Integer>();
}
If you want to avoid Java warnings, and still have an array of ArrayList, you can abstract the ArrayList into a class, like this:
public class Individuals {
private ArrayList<Individual> individuals;
public Individuals() {
this.individuals = new ArrayList<>();
}
public ArrayList<Individual> getIndividuals() {
return individuals;
}
}
Then you can safely have:
Individuals[] group = new Individuals[4];
ArrayList<String> al[] = new ArrayList[n+1];
for(int i = 0;i<n;i++){
al[i] = new ArrayList<String>();
}
you can create a List[] and initialize them by for loop. it compiles without errors:
List<e>[] l;
for(int i = 0; i < l.length; i++){
l[i] = new ArrayList<e>();
}
it works with arrayList[] l as well.

Categories

Resources