user343649
user343649

Reputation:

How does one access an ArrayList of ArrayLists? (Generics?)

I'm trying to create a table class, who's rows and columns may expand or shrink, to store ints and strings as a first Java project. The data structure I'm trying to use to represent the table is an ArrayList of ArrayLists, where the initial array's elements all point to a new array list - so the initial array kind of serves as an entrance into rows. This would be a picture of how I have it in my mind, for reference:

enter image description here

The problem I'm having is accessing the inner ArrayLists. I've been reading a bit of documentation, and I can't seem to understand the big issue with why I'm not able to access the inner lists. Some code here:

import java.util.ArrayList;

public class Table {

    private int length, width;
    private ArrayList newTable;

    public Table() {
    this.length = this.width = 0;
    }

    /**
     * Testing a few functions
     */
    public static void main(String[] args) {
        // Just testing a few functions.
        Table list1 = new Table();
        list1.createTable(4, 4);
        list1.displayRow(1);
        list1.displayColumn(1);
        System.out.println("displayColumn done!");
        list1.displayEntireTable();
    }

    public void createTable(int tableLength, int tableWidth) {
        length = tableLength;
        width = tableWidth;

        this.newTable = new ArrayList();
        for (int i = 0; i < tableWidth; i++) {
            this.newTable.add(new ArrayList(tableLength));
        }
    }

    public void displayRow(int row) {
        System.out.println(this.newTable.get(row));
    }

    /**
     * This function displays the column of the table. Still work which
     * needs to be done here.
     * @param column 
     */
    public void displayColumn(int column) {
        if (this.newTable.size() >= column) {
            for (int i = 0; i < this.newTable.size(); i++) {
                // This doesn't work.
                System.out.println(this.newTable.get(i).get(column)); 
            }
        }
    }

    public void displayEntireTable() {

        for (int i = 0; i < this.newTable.size(); i++) {
        System.out.println(this.newTable.get(i));
        }
    }
}

I'm suspicious that the problem may rely the lack of use in generics, which I'm not quite as familiar with yet as I would like to be. So my question to you, stackoverflow, is whether this data structure - an ArrayList of ArrayLists - is even possible, and if so, where lays my problem?

Upvotes: 2

Views: 9163

Answers (5)

falsarella
falsarella

Reputation: 12447

Using Java 1.7 generics improvements:

import java.util.ArrayList;
import java.util.List;

public class Table {

    private int length, width;

    private List<List<String>> newTable;

    public Table() {
        this.length = this.width = 0;
    }

    /**
     * Testing a few functions
     */
    public static void main(String[] args) {
        // Just testing a few functions.
        Table list1 = new Table();
        list1.createTable(4, 4);
        list1.displayRow(1);
        System.out.println("displayRow done!");
        list1.displayColumn(1);
        System.out.println("displayColumn done!");
        list1.displayEntireTable();
        System.out.println("displayEntireTable done!");
    }

    public void createTable(int tableLength, int tableWidth) {
        length = tableLength;
        width = tableWidth;

        //by java 1.7 diamond feature, some generics can be hidden
        this.newTable = new ArrayList<>();
        for (int i = 0; i < tableWidth; i++) {
            List<String> columns = new ArrayList<>();
            for (int j = 0; j < tableLength; j++) {
                columns.add(new String("test"));
            } //added here
            this.newTable.add(columns);
        }
    }

    public void displayRow(int row) {
        System.out.println(this.newTable.get(row));
    }

    /**
     * This function displays the column of the table. Still work which
     * needs to be done here.
     * @param column 
     */
    public void displayColumn(int column) {
        for (int i = 0; i < this.newTable.size(); i++) {
            System.out.println("[" + this.newTable.get(i).get(column) + "]");
        }
    }

    public void displayEntireTable() {

        for (int i = 0; i < this.newTable.size(); i++) {
            System.out.println(this.newTable.get(i));
        }
    }
}

Upvotes: 2

user425367
user425367

Reputation:

Change your code that doesn't work to:

System.out.println(((ArrayList) this.newTable.get(i)).get(column)); 

ArrayList in ArrayList is certainly possibly.
And it is certainly not generics that prohibits you.
Generics is only a compile time check for mistakes and has nothing to do with it. You can complete leave it out, not advised as the probability for class cast exceptions due too mistakes is far larger.

Explanation. The compiler don't knows your ArrayList contains an ArrayList so it doesn't recognize the get method as it trys to invoke it on Object and not ArrayList. So the solution is to cast it if you wan't to use it without generics. However I would recomend to use generics and define your List like this.

private List<List<String> newTable;

Notice how I used List and not ArrayList. Typically your left hand assignment contains an Interface and the right hand an concrete class like ArrayList.

Upvotes: 0

tungi52
tungi52

Reputation: 642

First of all, what is your real problem? You don't add any data into the inner ArrayLists, so they are empty.

On the other hand, it is better if you create an object for a row, and store these objects in an arraylist.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726609

I think the problem is that you misunderstood the semantics of the new ArrayList(tableLength) call: it does not create an array list of tableLength elements; rather, it creates an ArrayList with the initial capacity enough to hold at least tableLength elements.

I am not sure what kind of elements you are planning to add to your ArrayList of ArrayLists, but here is one way to test your code that creates a two-dimensional ArrayList:

for (int i = 0; i < tableWidth; i++) {
    ArrayList toAdd = new ArrayList(tableLength);
    for (int j = 0; j != tableLength ; j++) {
        toAdd.add(new Integer(i*tableLength +j));
    }
    this.newTable.add(toAdd);
}

Upvotes: 3

Louis Wasserman
Louis Wasserman

Reputation: 198103

Sure it's possible, and I suspect your issues are related to generics, actually -- if you don't use generics, you'll have to do a bunch of casts, which may appear to you as if it just doesn't work.

I'd write this as something like

List<List<Object>> table;

and then I'd add rows by doing table.add(new ArrayList<Object>()), and access elements with table.get(i).get(j).

Upvotes: 2

Related Questions