6

I have to create a 2d array with unknown size. So I have decided to go with a 2d ArrayList the problem is I'm not sure how to initialize such an array or store information.

Say I have the following data

   0 connects 1
   2 connects 3 
   4 connects 5

....etc up to a vast amount of random connections

and I want to insert

true(1) into [0][1], 
true(1) into [2][3], 
true(1) into [4][5]. 

Can the array automatically update the column/rows for me

Any help is appreciated thanks

xiao
  • 1,718
  • 4
  • 23
  • 31

8 Answers8

22

I'm not sure how to initialize such an array or store information.

Like this for instance:

List<List<Integer>> twoDim = new ArrayList<List<Integer>>();

twoDim.add(Arrays.asList(0, 1, 0, 1, 0));
twoDim.add(Arrays.asList(0, 1, 1, 0, 1));
twoDim.add(Arrays.asList(0, 0, 0, 1, 0));

or like this if you prefer:

List<List<Integer>> twoDim = new ArrayList<List<Integer>>() {{
    add(Arrays.asList(0, 1, 0, 1, 0));
    add(Arrays.asList(0, 1, 1, 0, 1));
    add(Arrays.asList(0, 0, 0, 1, 0));
}};

To insert a new row, you do

twoDim.add(new ArrayList<Integer>());

and to append another element on a specific row you do

twoDim.get(row).add(someValue);

Here is a more complete example:

import java.util.*;

public class Test {

    public static void main(String[] args) {

        List<List<Integer>> twoDim = new ArrayList<List<Integer>>();

        String[] inputLines = { "0 1 0 1 0", "0 1 1 0 1", "0 0 0 1 0" };

        for (String line : inputLines) {
            List<Integer> row = new ArrayList<Integer>();

            Scanner s = new Scanner(line);
            while (s.hasNextInt())
                row.add(s.nextInt());

            twoDim.add(row);
        }
    }
}
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • I need to specified a specific Row by Column. How do I insert a number into [0][1], [0][2], etc.. of this arrayList? – xiao Feb 16 '11 at 22:24
  • @eNetik, to set a particular value you would `toDim.get(x).set(y, value);` However, that assumes you constructed the empty array already. You must construct the array in a manner similar to the code above initially (even if you just set all values to zero) for an update to have something to update. – Edwin Buck Feb 16 '11 at 22:28
  • @eNetik, added a more complete example. – aioobe Feb 16 '11 at 22:30
  • @Edwin Buck, I am unaware of the array size. Its a file read where I need to create an adjacency matrix based on connected nodes. So I need to set right off the beginning array[0][1] = 1. and as the file continues to read I need to continue this process.. I was wondering if the arrayList builds its row/columns by itself after I add items to it – xiao Feb 16 '11 at 22:42
  • No, ArrayLists don't "pad with zeros" or anything like that if you try to enter a value at a specific index. You can append, and update values in the middle, but you can't "add values at arbitrary indices". – aioobe Feb 16 '11 at 22:44
  • @aioobe +1 there.. go to sleep – OscarRyz Feb 16 '11 at 22:44
17
List<List<Integer>> array = new ArrayList<List<Integer>>();
// add row:
array.add( new ArrayList<Integer>() );
// add a column:
array.get( array.size() -1 ).add( 1 );

Working demo:

import java.util.*;
import static java.lang.System.out;
class Load { 
    public static void main( String ... args ) { 

        List<List<Integer>> array = new ArrayList<List<Integer>>();

        Scanner input = new Scanner(System.in);
        out.println("Enter n:");
        int n = input.nextInt();

        out.println("Enter m:");
        int m = input.nextInt();

        out.println("Enter the values:");

        for( int i = 0 ; i < n ; i++ ) { 
            // add row:
            List<Integer> list = new ArrayList<Integer>();
            array.add( list );
            for( int j = 0 ; j < m ; j++ ) { 
                // add a column:
                // array.get( array.size() -1 ).add( 1 ); or
                list.add( input.nextInt() );
            }
        }
        out.println("Result:");
        out.println( array );

    }
}

Output:

C:\>java Load
Enter n:
3
Enter m:
6
Enter the values
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Result:
[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17]]
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
0

The short answer to the followup question is

array.get(i1).put(i2, value);

but both the get and put could fail if the size of the ArrayList is <= the index. So if you want to be able to fill in arbitrary values, you need to write methods to expand as necessary. The call would then be something like

putCell(getRow(array, i1), i2, value)

where getRow() knows how to grow the ArrayList of ArrayList, and putCell() knows how to grow the ArrayList.

Vance Maverick
  • 812
  • 6
  • 4
0

If you don't have all of the data in advance to be able to leverage aioobe's solution, you could use a Table from Google's Guava library.

Table<Integer,Integer,Integer> matrix = new HashBasedTable<Integer,Integer,Integer>();
matrix.put(rowIndex,columnIndex,value);

The primary drawback of this is that it's not incredibly fast or memory efficient if you are working with a large quantity of data, as everything is a hash lookup and primitives are wrapped by Integer.

rfeak
  • 8,124
  • 29
  • 28
0

Well, if you know you have 3 rows and 5 columns (as shown in your data example) you could initialize it as follows:

int[][] a = new int[3][5]; 

However, if the number of rows changes you could do something like this:

String dataStr = "0,1,0,1,0:0,1,1,0,1:0,0,0,1,0";

String[] rows = dataStr.split(":");

String[] cols = rows[0].split(",");

Now you can initialize:

int[][] a = new int[rows.length][cols.length];

This will accomodate changing row and col size. Might not be the most elegant approach but it should work.

KJYe.Name
  • 16,969
  • 5
  • 48
  • 63
Damon
  • 718
  • 2
  • 8
  • 22
0

Your example looks like you want to have a map from pairs of ints to booleans (with the default value being false). If this is a sparse map (i.e. really most of the positions are false), you may be better with something like a HashSet or similar (with being a class encapsulating two ints with a suitable implementation of hashCode and equals).

class IntPair {
   int first;
   int second;
   public boolean equals(Object o) {
      return o instanceof IntPair &&
         ((IntPair)o).first == first &&
         ((IntPair)o).second == second;
   }
   /** optimized for small numbers */
   public int hashCode() {
       return first + second * 44729;
   }
   public String toString() {
     return "(" + first + ", " + second + ")";
   }
}

Then, to say "0 connects 1" you would write

set.add(new IntPair(0,1));

It really depends on what operations you want to use afterwards - such a HashSet has quick lookup and change and uses not too much space, but you can't get quickly "all neighbours of node 1". If you need such access, you may simply want a class like

class Node {
   int id;
   Set<Node> neighbours;
}

and additionally a list/array/set of such nodes.

The question "array of unknown size" is not specific enough to really answer competently.

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
0

Since you only need to store booleans in that 2D array, I would say the most suitable data structure (as both memory consumption and useful interface) would be a java.util.BitSet, which is basically a class that models a bit array:

As it's a 2D array, I think the way to go would be a:

List<BitSet> bitArrays = new ArrayList<BitSet>();

In the List, you cannot just say: "here's the 5th element" without inserting the first 4 elements. But in the BitSet, you can simply set() whatever bit you need and it will automatically expand to the required size.

Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
0
  import java.util.*;
    public class ArrayListDS { 
        public static void main( String [] args ) { 

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

           Scanner sc = new Scanner(System.in);

           System.out.println("Enter the number of row: ");
           int n = sc.nextInt();

           for(int i = 0; i < n; i++){

               ArrayList<Integer> col = new ArrayList<Integer>();
               row.add(col);

           System.out.println("Enter the number of column: ");
           int m = sc.nextInt();

               for(int j = 0; j < m; j++){
                    col.add(sc.nextInt()); 
               }
               System.out.println();
           }
           System.out.println(row);
        }
    }
Kariba
  • 11
  • 3