DEV Community

Zander Bailey
Zander Bailey

Posted on • Updated on

Java Lists: Lists of Lists

A List of Lists might seem unnecessarily complicated, but it comes up in Java more than you might think ,when when you do come across one it’s good to know how to deal with it. When dealing with a List of Lists, it is easy to lose sight of the scope of the List, because there is an extra layer to deal with. Normally when you create an empty List you can immediately begin populating it with new items, but a List of Lists takes an extra step. Remember, the List of Lists doesn’t contain any actual items, it contains the Lists that contain the items. Unlike creating a 2-dimensional array, a List of Lists contains no actual Lists upon creation, and needs to be populated with Lists before you can begin filling those individual Lists. Don’t worry, we’re going to look at some examples of how this works. Let’s say we want to make a List that contains a list for each floor of and apartment building, with the apartment numbers for each floor. Here’s how we instantiate the List:

ArrayList<ArrayList<Integer>> roomList = new ArrayList<ArrayList<Integer>>();

So far, not too bad. There are two main ways we can start populating it. First, let’s add the first floor:

roomList.add(new ArrayList<Integer>());
roomList.get(0).add(101);
roomList.get(0).add(102);
roomList.get(0).add(103);

Notice how first we have to add a new List to the main List, and then retrieve that List in order to start adding individual room numbers. In this case we don’t have to give the List we are adding a name since it won’t need one once it is stored inside the main List. The other way we can add a floor is to create it first, then add it. Let’s try this with the second floor:

ArrayList<Integer> floor2 = new ArrayList<Integer>();
floor2.add(201);
floor2.add(202);
floor2.add(203);
roomList.add(floor2);

In this case we create the floor List and finish populating it before adding it directly to the main List. Now let’s talk a little about copying a List of Lists. Earlier we went over the difference between a shallow copy and a deep copy, and how we have to copy each item to make a distinct copy of the List instead of the just the references. But now we’re dealing with a List of other things that reference other things, so how to we copy that? We have to go one level deeper. It seems a little crazy, but we have to go over each List and create a deep copy of that List, and then place those lists in a new List in order to make a deep copy of a List of Lists. IT will look something like this:

/* First we’ll create a new List */
ArrayList<ArrayList<Integer>> newBuilding = new ArrayList<ArrayList<Integer>>();

/* Next we iterate through the Lists to get every item */
For(int i=0;i<roomList.size();I++){
    newBuilding.add(new ArrayList<Integer>());
    for(int room: roomList.get(I)){
        newBuilding.get(I).add(room);
    }
} 

And now we have successfully created a deep copy of our List of Lists. Lists can be very powerful, and there are many reasons to use them, but if you are going to be stacking Lists inside of other Lists it can be costly in both space and runtime, so it is wise to consider using multidimensional arrays instead.

Top comments (1)

Collapse
 
pawelsalawa profile image
Pawel Salawa • Edited

Few suggestions/advises:

  1. Use diamond operator to simplyfiy generic collections creation. For example: ArrayList<ArrayList<Integer>> list = new ArrayList<>();
  2. Use generalized types for declaration, unless you have good reason to use specific types. For example: List<List<Integer>> list = new ArrayList<>();
  3. In most cases the "foreach" of Java is suffficient to iterate through collection. The C-like style with indexes is still applicable in some cases, but you will mostly use the "foreach": for (List<integer> subList : list) {...}