tags:

views:

704

answers:

4

I want to store 2 dimensional values i.e. B-1, C-2, D-3, etc.

Any suggestions on the classes or interfaces that can be used?

+1  A: 

I am assuming you need a data structure in Java to store these values.

You could define a 2D array in Java using the following syntax.

String[][] strArr = new String[5][5]; //defines a 5*5 String array 
String[][] strArr2 = new String[1][2]; //defines a 1*2 String array

Please note that the arrays can hold values of only 1 datatype. The specific items can be dereferenced using something like

System.out.println(strArr2[0][1]);

For your specific example, you could also use java.util.Map class and store the data as key-value pairs but this requires the "keys" to be unique. e.g.,

Map<String,Integer> keyval = new HashMap<String, Integer>();
keyval.put("B",1);
keyval.put("C",2);
keyval.put("D",3);
keyval.put("D",4); //wrong. will overwrite the previous entry.
Rahul
+2  A: 

If you're looking to do a spreadsheet-type application (deduced, possibly wrongly, from the spring-framework tag and the B-1/C-2 names), sparse arrays are probably the way to go.

Colt has one such implementation.

I answered a similar question here.

paxdiablo
A: 

I guess what you need is a Map of ArrayLists:

HashMap<String, ArrayList<YourClass>> map;

This way B-1 would be map.get("B").get(1);

tulskiy
+3  A: 

There are three basic types of multidimensional arrays:

  1. Fixed. Think of a chess board, which is always 8x8 (variants notwithstanding). But this can also mean something that is variable but fixed upon instantiation;
  2. Sparse. arrays where there are lots of empty space between values. Spreadsheets typically fit this description but what is and isn't sparse is typically a subjective judgement; and
  3. Dense. The opposite of sparse. Most or all possible values are used.

Java doesn't have a native multidimensional array type. Java has arrays of arrays, which isn't quite the same thing. For example, this is legal Java:

int arr[][] = new int[] {
  new int[3],
  new int[4],
  new int[5]
};

Fixed arrays can be done this way but it can be awkward. It's often easier to use a single dimensional array with an object wrapper:

public class Chessboard {
  public final static DEFAULT_X = 8;
  public final static DEFAULT_Y = 8;
  public final static DEFAULT_SIZE = DEFAULT_X * DEFAULT_Y;

  private final int x;
  private final int y;
  private final int size;
  private final Piece squares[];

  public Chessboard() {
    this(DEFAULT_X, DEFAULT_Y);
  }

  public Chessboard(int x, int y) {
    if (x < 2) {
      throw new IllegalArgumentException("x (" + x + ") must be 2+");
    }
    if (y < 2) {
      throw new IllegalArgumentException("y (" + y + ") must be 2+");
    }
    this.x = x;
    this.y = y;
    size = x * y;
    pieces = new Piece[size];
  }

  public Piece get(int x, int y) {
    return pieces[y * this.x + x];
  }

  public Piece get(String xy) {
    // eg 'h3' => (7,2)
    return get(xy.charAt(0) - 'a', xy.charAt(1) - '0');
  }

  // etc
}

This can of course be done with arrays of arrays instead.

Sparse arrays tend to be implemented in Java with maps:

public class Sparse2DArray<T> {
  public final static int MAX_X = 8192;
  public final static int MAX_Y = 8192;

  private final Map<String, T> array = new HashMap<String, T>();
  private final Pattern XY = Pattern.compile("^([A-Za-z]+)([0-9]+)");

  public T get(int x, int y) {
    if (x < 0 || x >= MAX_X) {
      throw new IllegalArgumentException("x (" + x + ") must be 0 to " + (MAX_X-1));
    }
    if (y < 0 || y >= MAX_Y) {
      throw new IllegalArgumentException("y (" + y + ") must be 0 to " + (MAX_Y-1));
    }
    return array.get(x + "," + y);
  }

  public T get(String xy) {
    Matcher m = XY.matcher(xy);
    if (!m.matches()) {
      throw new IllegalArgumentException("xy (" + xy + ") must be letters followed by digits");
    }
    String s = m.group(1).toUpperCase();
    int multiplier = 1;
    int x = 0;
    for (int i=s.length()-1; i>=0; i--) {
      x += (s.chartAt(i) - 'A') * multiplier;
      multiplier *= 26;
    }
    int y = Integer.valueOf(m.group(2));
    return array.get(x, y);
  }

  // etc
}

You can also do this by constructing an N-dimensional key class to use as the map key. It would need the appropriate equals() and hashCode() methods defined and would probably be a cleaner solution but the above will work.

Obviously if you were going to store every value of a 100x100 array in the sparse array class there would be an overhead (as all maps have overheads). This brings in the dense array. The sparse array only stores values where values are set. The dense array stores a value for every possible key (within the specified range).

Also the dense array is similar to the fixed array but not quite the same. Fixed arrays are hard to extend once created (well, it's an expensive operation so it's generally not allowed) whereas dense arrays might be built to be extended, like you could use them for a spreadsheet and extend the max X and Y values are the user uses more and more cells so you define a rectangle encompassing all used values.

cletus
OMG, what was that.. :o +1 for this thesis
Rakesh Juyal