Handling arraylist of arraylists with each having different objects [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have this, three different array lists:
ArrayList<type1> alista = new ArrayList<>();
ArrayList<type2> blistb = new ArrayList<>();
ArrayList<type3> clistc = new ArrayList<>();
I then create a new array list and put those 3 array lists into it:
ArrayList<Object> all_lists = new ArrayList<Object>();
all_lists.add(alista);
all_lists.add(blistb);
all_lists.add(clistc);
How do I add or remove objects inside all_lists: alista, blistb and clistc? I want to pass this all_lists back and forth between my methods inside my main(). I know doing it this way is probably wrong but I'd like to get this to work before I fix that with doing it better.
For example how do I get blistb out of that, then add one type of type2 I've created and then remove one type2 (from blistb). And then put it back (or create new all_lists?) into all_lists?

If I understand correctly, you want to be able to pass around all your data and make changes to the lists. First I would change the type of your lists to the List interface. This does not the function of your code but makes it easier if you'd want to change the List implementation in the future and it also saves some characters:
List<Type1> alista = new ArrayList<>();
List<Type2> blistb = new ArrayList<>();
List<Type3> clistc = new ArrayList<>();
We'll do the same with all_lists and at the same time, change its generic type to List to make life easier later:
List<List<Object>> allLists = new ArrayList<Object>();
(If Type1, Type2 and Type3 have some common ancestor that they all extend from, change the Object above to that type.)
To get one of your lists, blistb for instance, you need to know it's position in all_lists:
List<Type2> blistbReference = allLists.get(1); // Index starts from 0
This will probably be hard to maintain and to keep track of. There is also a risk that some future code change changes the order which will cause errors and headaches.
A better way to handle your lists would be to wrap them in a data object:
public class AllLists {
private List<Type1> alista;
private List<Type2> blistb;
private List<Type3> clistc;
public AllLists(List<Type1> alista, List<Type2> blistb, List<Type3> clistc) {
this.alista = alista;
this.blistb = blistb;
this.clistc = clistc;
}
public List<Type1> getAlista() {
return alista;
}
public List<Type1> getBlistb() {
return blistb;
}
public List<Type1> getClistc() {
return clistc;
}
}
// ......
AllLists allLists = new AllLists(alista, blistb, clistc);
You can now get your lists easily from the AllLists object and modify them as you like.
Type2 t = new Type2;
allLists.getBlistb().add(t);
You don't need to "put the list back" since Java is pass by reference. When you get the blistb from allLists, you are getting a reference to the same list object. Any changes to the reference is a change to the original list.
I changed type and variable names to be more standardized.

You should declare all_lists as a List of Lists; then, you can directly add and remove items to the Lists at specific indexes.
List<List> all_lists = new ArrayList<>();
all_lists.add(new ArrayList<A>(Arrays.asList(new A(1), new A(2), new A(3))));
all_lists.add(new ArrayList<B>(Arrays.asList(new B(4), new B(5))));
all_lists.add(new ArrayList<C>(Arrays.asList(new C(6))));
all_lists.get(1).add(new B(3));//add element to B List

You just need to keep track of which array is which:
in:
ArrayList<Object> all_lists = new ArrayList<Object>();
all_lists.add(alista);
all_lists.add(blistb);
all_lists.add(clistc);
all_lists.get(0) is alista
all_lists.get(1) is blistb
all_lists.get(2) is clistc
You remove the object from blistb by knowing which index it is in that list and removing it like normal.
all_lists.get(1).remove(2);

all_lists should be declared as ArrayList<ArrayList> (using raw-type which would require #SuppressWarnings("unchecked")).
#SuppressWarnings("unchecked")
ArrayList<ArrayList> all_lists = new ArrayList<>();
all_lists.add(alista);
all_lists.add(blistb);
all_lists.add(clistc);
clistc.add(new type3());
all_lists.get(0).add(new type1()); // add type1 object to alista
all_lists.get(1).add(new type2()); // add type2 object to blistb
all_lists.get(2).remove(0); // remove the 1st element of clistc
However, it would be better and more type-safe object-oriented way to create a wrapper class instead of all_list:
class ListWrapper {
private List<type1> aListA;
private List<type2> bListB;
private List<type3> cListC;
// constructor(s), getters/setters
public void addType1(type1 t1) {
aListA.add(t1);
}
// etc.
}

Related

Java ArrayList with 2 columns

I need to use an array list as I don't know how many rows I will need but I know I'll need 2 columns. I'm unsure of how to create such an array list, add to both columns and read data from both columns. Both columns will contain integers.
I have seen some suggest:
ArrayList<Arraylist<Integer>> name = new ArrayList<ArrayList<Integer>>();
but I can find an explanation of how to add to both columns.
I've also seen:
ArrayList<Integer[][]> name = new ArrayList<Integer[][]>();
and different variations of where and the number of square brackets.
Thanks.
Java is Object Oriented language, so why not create ArrayList<Column> ?
You can create a class Column which will cover your requirements: it can have setters and getters, and if you need to support other types other than Integer you can generify it. For example:
class Column<T> {
private T value;
public Column(T value) {
this.value = value;
}
public getValue() {
return this.value;
}
}
Then you declare:
List<Column<Integer>> list = new LinkedList<>();
list.add(new Column<Integer>(5));
System.out.println(list.get(0).getValue())
Example how create two dimension structure use lists like you to do:
List<List<Integer>> names = new ArrayList<>();
List<Integer> row = new ArrayList<>();
row.add(1); // first column
row.add(2); // second column
names.add(row); // add row with column
System.out.println(names.get(0).get(0)); // get first column from first row
System.out.println(names.get(0).get(1)); // get second column form first row
But best way is use Custom object like this:
class CustomRow {
private int col1;
private int col2;
// getters and setters
}
List<CustomRow> tables;
CustomRow cr = new CustomRow();
cr.setCol1(1);
cr.setCol2(2);
tables.add(cr);
Something like this:
public MyObject {
Integer integer1;
Integer integer2;
}
List<MyObject> myObjList = new ArrayList<>();
MyObject mo = new MyObject(){
...
myObjList.add(mo);
You could try
a Map and use the key and the value to hold values
a List of tuples
a List of Lists as you suggested
You didn't give enough information as to what you actually want to do, but if you have to use a List as a base, I'd typically go with a List of custom Tuple objects, each holding two values.
You can try creating a simple POJO class called Row and have two variables as column1 and column2. Then add this Row object to your list.
You basically need to create an ArrayList that holds an ArrayList of type Integer. You can then add two of these ArrayLists into the main array list.
List<List<Integer>> myList = new ArrayList<>();
List<Integer> x = new ArrayList<>();
x.add(5);
x.add(6);
List<Integer> y = new ArrayList<>();
y.add(5);
y.add(6);
myList.add(x);
myList.add(y);
Based off this answer:
How do I declare a 2D String arraylist?

Java list changed when update another one

Supposing we have:
public class Test {
private List<String> mWorkList;
private List<String> mOriginalList;
public Test(List<String> list) {
mWorkList = list;
mOriginalList = list;
}
public void updateData(List<String> newList) {
mWorkList.clear();
mWorkList.addAll(newList);
}
}
I want to change only mWorkList but mOriginalList is changed too when I call updateData(List<String>).
So how should I do it to keep mOriginalList as initially assigned in constructor?
In Java you pass variables by their reference. This means that whenever you do an assignment like mWorkList = list the variable mWorkList will point to the same place in memory where list is currently pointing. If you do mOriginalList = list, then mOriginalList will also point to that position. I.e. all three lists refer the same object at that point.
If you want independent lists you need to copy all values from the list to a new list like this:
List<String> myList = new ArrayList<>(otherList);
This constructor of ArrayList automatically adds all values from the other list, here is its documentation.
Your code could then look like:
public Test(List<String> list) {
mWorkList = new ArrayList<>(list);
mOriginalList = new ArrayList<>(list);
}
Or if you don't intent to change mOriginalList you could also leave it as mOriginalList = list. But then bear in mind that if the user makes changes to list (which comes from outside of your class) they will also be reflected in your mOriginalList which could easily lead to nasty bugs.
You are setting both list with the same instance reference with
mWorkList = list;
mOriginalList = list;
You need to create a new instance for mOriginalList by duplicating the list. This can be done with one of the constructor of ArrayList(Collection).
mOriginalList = new ArrayList<>(list);
Please note that the instances in both list are the same, so if you update an instance in list, it will be changed in mOriginalList. If you want to break that link too, you will need to clone the list and his content.
You should create new List object in function Test, because all your lists refer to one variable
public Test(List<String> list) {
mWorkList = new ArrayList<>(list);
mOriginalList = new ArrayList<>(list);
}
Whenever you assign a object to another object only the reference is assigned (Shallow copy). You should call copy constructor to make a deep copy.
public class Test {
private List<String> mWorkList;
private List<String> mOriginalList;
public Test(List<String> list) {
mWorkList = new ArrayList<>(list);
mOriginalList = new ArrayList<>(list);
}
public void updateData(List<String> newList) {
mWorkList.clear();
mWorkList.addAll(newList);
}
}
In java every variable is a reference, so in this case it's normal that both variable changes if you change one of them.
To keep a copy you have to create a new object and clone the original one.

Why can't you have a "List<List<String>>" in Java? [duplicate]

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 5 years ago.
In Java, why doesn't the following line of code work?
List<List<String>> myList = new ArrayList<ArrayList<String>>();
It works if I change it to
List<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();
At first, I thought maybe you can't have lists of an interface, but I can create a List<Runnable> just fine.
Ideas?
Generic types are more pedantic.
List means List or any sub-type, but <List> means only List. If you want a sub-type you need to have <? extends List>
I suspect you can use
List<List<String>> myList = new ArrayList<List<String>>();
The reason you can't do this is that you can be using a reference to a reference and with an extra level of indirection you have to be careful.
// with one level of indirection its simple.
ArrayList alist = new ArrayList();
List list = aList; // all good
list = new LinkedList(); // alist is still good.
With generics you can have two level of indirection which can give you problems so they are more pedantic to avoid these issues.
// with two levels of indirection
List<ArrayList> alist = new ArrayList<ArrayList>();
List<List> list = (List) alist; // gives you a warning.
list.add(new LinkedList()); // adding a LinkedList into a list of ArrayList!!
System.out.println(alist.get(0)); // runtime error
prints
Exception in thread "main" java.lang.ClassCastException: java.util.LinkedList
cannot be cast to java.util.ArrayList
Lets start with this:
ArrayList<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();
This is creating an ArrayList whose elements are ArrayLists.
Now suppose we could assign that to
List<List<String>> myList2 = myList.
Now, we should be able to do this:
myList2.add(new LinkedList<String>());
But that means we have added a LinkedList to a list whose elements are supposed to be ArrayLists. Ooops!!!
In reality, the assignment of myList to myList2 is not legal ... and that ensures that it is not possible to add the wrong kind of List<String> to the ArrayList<ArrayList<String>> object. (No Peter, it is not just pedantry :-) )
Only the top level collection can be declared as an implementing class, while the nested ones must remain interfaces until you actually create instances:
List<List<String>> rootList = new ArrayList<List<String>>();
and then when you create an element to go in, you make it an implementation:
List<String> nodeList = new ArrayList<String>();
rootList.add(nodeList);
Its comparing Type from left(declaration) side to Type from right(instantiation) side. In Left, your type is List<String> while in right, it's ArrayList<String>. If complaining about the difference.
Please update the right side(instatiation) as List i.e.
List<List<String>> myList = new ArrayList<List<String>>();
This should work fine.
I know this is an old question but I just wanted to share my idea.
Instead of making a List of Lists, I personally just make a List of Type[] (List<Type[]> listArray = new ArrayList<Type[]>();), I generate a separate List of just Type (List<Type> list = new ArrayList<Type>();), then .add(list.toArray()). This way, it's clearer and easier to read than the List of Lists syntax which is confusing.
For example, in a recent project where I had an input file where each line with only a "0" meant a new line in the original (it was an encryption algorithm):
String[] input = getInputContents(inFile);
List<String> currentBuffer = new ArrayList<String>();
List<String[]> buffers = new ArrayList<String[]>();
for(String line : input) {
if(line.equals("0")) {
buffers.add((String[])currentBuffer.toArray());
currentBuffer = new ArrayList<String>();
} else {
currentBuffer.add(line);
}
}
the list<list<string>> l1=new list<list<string>>(); is allowed if the list contains one more list inside the list.
public final class CPanelXMLBuilder extends PanelXMLBuilder {
public CPanelXMLBuilder(AuthenticatedUser pAuthenticatedUser, Map<String, Object> pSessionMap, Map<String, Object> pRequestMap, String pPanelTemplate) throws Exception {
super(pAuthenticatedUser, pSessionMap, pRequestMap, pPanelTemplate, null);
}
public Map<String, Object> buildXMLDocument(List<List<String>> pDetailsList) {
if (pDetailsList.size() == 1) {
List<String> pCustomerDetail = pDetailsList.get(0);
xmlDocument.getRootElement().getChild("E_SHOW1").setText(pCustomerDetail.get(0));
xmlDocument.getRootElement().getChild("E_SHOW2").setText(pCustomerDetail.get(1));
xmlDocument.getRootElement().getChild("E_SHOW3").setText(pCustomerDetail.get(2));
xmlDocument.getRootElement().getChild("E_SHOW4").setText(pCustomerDetail.get(3));
xmlDocument.getRootElement().getChild("E_SHOW5").setText(pCustomerDetail.get(4));
xmlDocument.getRootElement().getChild("ServerTimestamp").setText(pCustomerDetail.get(5).substring(0, 19));
} else {
xmlDocument.getRootElement().getChild("AlertType").setText("INFO");
xmlDocument.getRootElement().getChild("Alert").setText("There is no matching record.");
}
requestMap.put(RequestMapKeys.XML_DOCUMENT, xmlDocument);
return requestMap;
}
}

copy constructor with ArrayList parameter

I'm trying to make a copy constructor for an object and one of the parameters is an ArrayList.
when creating the ArrayList object, I had in mind to use the ArrayList constructor where you can pass a collection as a parameter, but I'm not sure if this will work as a "pointer" to the arraylist or if this will create a whole new arraylist object
This is the code I have
public MyObject(MyObject other)
{
this.brands= other.brands;
this.count = other.count;
this.list = new ArrayList<Integer>(other.list); // will this create a new array list with no pointers to other.list's elements?
}
I'm not sure if this will work as a "pointer" to the arraylist or if
this will create a whole new arraylist object
When you use new, it will create a brand spanking new instance of ArrayList (this is what you have asked). But it will not also automatically create copies of its elements (which I think is what you are looking for). What this means is, if you change a mutable object in the new List, it will also change in the original List, if it is still around. This is because the List only holds references (kinda sorta but not exactly pointers) to the Objects in them, not the actual Objects themselves.
For example:
Person person = new Person("Rob"); // create a new Object
List<Person> myList = new ArrayList<Person>();
myList.add(person);
// Create another list accepting the first one
List<Person> myList2 = new ArrayList<Person>(myList);
for(Person p : myList2) {
p.setName("John"); // Update mutable object in myList2
}
person = new Person("Mary"); // stick another object into myList2
myList2.add(person);
for(Person p : myList2) {
System.out.println(p.getName()); // prints John and Mary as expected
}
for(Person p : myList) {
System.out.println(p.getName()); // prints only one result, John.
}
So you can see that the two Lists themselves can be modified independently, but when you use the constructor accepting another List, both will contain references to the same Person instances, and when the state of these objects change in one List, they will also change in the other (kinda sorta just like pointers).

Setting a list equal to list using equal sign or copy constructor?

This is a simple question but if I do
List<Object> list = getObjectsFromDatabase();
This would not be the correct way to handle this?
But this would?
List<Object> firstList = getObjectsFromDatabase();
List<Object> list = new ArrayList<Object>(firstList);
Or if I had a class
public class ReportDisplayModel<T> {
public ReportDisplayModel(List<T> data) {
this.data = data;
}
public List<T> data;
}
And I wanted to set the data in this model I would use the constructor?
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>(getData());
Instead of
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>();
model.data = getData();
Just need a clarification. Thanks.
It depends entirely on what getData() returns.
usually it is made to return Collections.unmodifiableList(result) so that clients can't modify the result.
if this result is not used anywhere else, and modifications to it doesn't mess with anything, it is fine to use the result as-is
It is rarely needed to use the copy constructor - use it when you are sure that modifying the data will impact some other component.
Regarding
List<Object> list = getObjectsFromDatabase();
vs
List<Object> firstList = getObjectsFromDatabase();
List<Object> list = new ArrayList<Object>(firstList);
either approach is fine. Depends on if you want list to refer to the list returned by getObjectsFromDatabase() or if you want it to refer to a copy of it.
If simply want to, say, print the database objects, the first approach is fine.
If you want to, say, filter out half of the database objects (i.e., remove objects from the list), and you can't say for sure that getObjectsFromDatabase() returns a mutable list, then you'll have to go with the second approach.
Regarding
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>(getData());
vs
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>();
model.data = getData();
I'd prefer the first method. Simply because I wouldn't want to worry about null pointer exceptions etc if I accidentally do something like
ReportDisplayModel<Object> model = new ReportDisplayModel<Object>();
model.printData();
model.data = getData();
I don't quite get your question, but I'll give it a try.
The main difference is that using the copy constructor creates a new independent copy of the list, i.e.
List<Object> firstList = getObjectsFromDatabase(); // firstList is the list returned by the database
List<Object> list = new ArrayList<Object>(firstList); //list is an independent copy of firstList
Now if you change firstList the list returned by getObjectsFromDatabase() would be changed as well (or would throw an exception if changes are not supported). On the other hand list could freely be changed without the original list being affected.
Avoid using the equal sign, because it breaks encapsulation (bad practice). Go for the copy constructor (best practice).

Categories