0

I need to get three levels down into an array list. Here is my code on how I create the final product "rowList":

ArrayList<ArrayList> rowList = new ArrayList<ArrayList>();
ArrayList<ArrayList<String>> appList =new ArrayList<ArrayList<String>>();
ArrayList<String> arr = new ArrayList<String>();

int Id = -1;
int cc = rsmd.getColumnCount();
while(rs.next()){
    if(Id == -1){
        arr.add(rs.getString("name"));
        Id= Integer.parseInt(rs.getString("Id"));
    }
    if(Id!= Integer.parseInt(rs.getString("Id"))){
        Id= Integer.parseInt(rs.getString("Id"));
        rowList.add(appList);
        appList = new ArrayList<ArrayList<String>>();
        arr.add(rs.getString("name"));

    }

    for(int i=2; i < rsmd.getColumnCount();i++){
        arr.add(rs.getString(rsmd.getColumnName(i)));
    }
    appList.add(arr);
    arr = new ArrayList<>();
}
rowList.add(appList);

So in the end rowlist will look something like this:

[0]
  [0]
   [0]Property 1
   [1]Property 2
   [2]Property 3
  [1]
   [0]Property 1
   [1]Property 2
   [2]Property 3
[1]
  [0]
   [0]Property 1
   [1]Property 2
   [2]Property 3
  [1]
   [0]Property 1
   [1]Property 2
   [2]Property 3

So my question would be how to get to the properties, the last level in the nested array? I can use rowList.get(0).get(0).toString() to return the string array, but rowList.get(0).get(0).get(0) doesn't work, and instead gives the error: cannot find symbol.

I would also like to be able to remove a property after I've retrieved it and set it to a string. That part can easily be worked around though, so it isn't vital.

4
  • The repeated calls to Integer.parseInt(rs.getString("Id")) are very redundant... Commented Aug 12, 2016 at 19:00
  • When I say I get a string array, I mean if I run this: rowList.get(0).get(0).toString(); then I get this: [Property1, Property2, Property3, Property4]. Does that help? Commented Aug 12, 2016 at 19:02
  • Can you show the code which populates rowList? Commented Aug 12, 2016 at 19:08
  • @Code-Apprentice I did. 13th line I posted and also the last row. rowList.add(appList); Commented Aug 12, 2016 at 19:26

2 Answers 2

3

This is because you're using a raw type:

ArrayList<ArrayList> rowList = new ArrayList<ArrayList>();

rowList.get(0) returns an ArrayList. Antoher .get(0) will return an Object, because you're using a raw type. And Object does not have a get method.

But Object does have a toString method, so you can call toString.


You simply have to change the declaration. This can be made easier using the diamond:

ArrayList<ArrayList<ArrayList<String>>> rowList = new ArrayList<>();
ArrayList<ArrayList<String>> appList = new ArrayList<>();
ArrayList<String> arr = new ArrayList<>();
Sign up to request clarification or add additional context in comments.

1 Comment

This works, but you are missing one > right before rowList. Once I confirm I will check you off as the correct answer.
2

Okay, let's think about the type of each result in the chained calls rowList.get(0).get(0).get(0). The easiest way to do this is to break each call into its own line so that we can figure out the type we need for the variable declaration. First of all, look at the declaration of rowList:

ArrayList<ArrayList> rowList = new ArrayList<ArrayList>();

This tells us that rowList.get(0) will return an ArrayList:

ArrayList arr = rowList.get(0);

Now rowList.get(0).get(0) is equivalent to arr.get(0). But this returns an Object:

Object obj = arr.get(0);

So rowList.get(0).get(0).get(0) is equivalent to obj.get(0). However, Object does not have a method named get(). This is why you get an error message.

In general, you should be very careful when chaining method calls. Typically this syntax is only used when a method returns a reference to the calling object. That way the return type is always the same and much easier to keep track of. When the return type differs on each successive method call, it can be difficult to keep track of.

The problem is that the ArrayList returned by rowList.get(0) is a raw type. So another get() call only returns an Object. You should use generics to specify the type of object in the "rows":

ArrayList<ArrayList<ArrayList<String>>> rowList = new ArrayList<>();

As you see here, generics can be used as the type inside of any <> just like you already did for the outermost level of ArrayList in your originaly code. (Note that in JDK 7+, you can use the diamond operator when creating an ArrayList. This greatly reduces duplicating the type information that already appears in the declaration.)

Better yet, you can declare your variables using the List interface in order to provide some flexibility in the concrete type used:

List<List<List<String>>> rowList = new ArrayList<>();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.