15

I want to use a collection in place of 2D array so that I don't need to give its size at the time of declaration and I can add as many elements as I want dynamically.

Amit
  • 33,847
  • 91
  • 226
  • 299

9 Answers9

7

The problem with List> is you have to redimension each row if you want to redimension your matrix.

If you want to use a sparse matrix, or maybe an infinite matrix you can do something like:

class SparseMatrix<X> {
  private Map<Coord, X> values = new HashMap<Coord, X>();

  public SparseMatrix() {
  }

  public X get(int x, int y) {
     return values.put(new Coord(x,y)); // null if there's no value
  }

  public void set(int x, int y, X value) { // you can use null (like in a List)
     values.set(new Coord(x,y), value);
  }

  private static class Coord {
    int x; int y;
    public Coord(int x, int y) {
       this.x = x;
       this.y = y;
    }

    @Override
    public boolean equals(Object other) {
       if (other instance of Coord) {
          Coord o = (Coord) other;
          return o.x == x && o.y == y;
       }
       return false;
    }

    @Override
    public int hashCode() {
       return o.x + o.y; // or some more clever implementation :)
    }

  }
}

Edit: Apache Commons HashCodeBuilder is a great tool for generating hash-codes.

Marcelo Assis
  • 5,136
  • 3
  • 33
  • 54
helios
  • 13,574
  • 2
  • 45
  • 55
  • 1
    Your hashCode may overflow - however you *do* have commented it accordingly... :) – Esko Jan 12 '10 at 19:58
  • Sharp view!!! There's an utility method: java.util.Arrays.hashCode(int[]) that makes a hashcode for an int[] but of course, it wouldn't be nice to create an array each time the hashChode is needed (or to have it created). Maybe we could copy it's implementation for only two integers: (31 + o.x) * 31 + o.y. But it seems to overflow anyway... (I think it doesn't matters, is it cyclic?). – helios Jan 13 '10 at 10:08
  • Does it matter in the hashCode() that x+y == y+x? – Adam Mar 03 '11 at 14:48
  • 1
    No, it doesn't matter. The important thing for hashCodes is that they give pretty distributed values so if you have N buckets you can use that hashCode to distribute them more or less uniformely (put object X in bucket `hasCode(X) % N`. That's why my implementation is not good: if you use low coordinates it gives low hashcodes. I'll add a reference to Apache HashCodeBuilder. It encapsulates this problem very very well. – helios Mar 11 '11 at 11:34
4

The easiest way is to use nested collections... say (assuming your values are Strings) List<List<String>> which can then be used like this:

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

// Pretend you fill it with values between these calls
String retrieve = fakeArray.get(0).get(0);

Edit: This was originally a Map<String,List<String>> which really doesn't make sense in this context.

However, you may want to see if Google Collections or Apache Commons Collections have something more specialized that you can use.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
2

What do you want to be able to do with it? I would probably simply use a Collection<Collection<Element>> (where Collection might be replaced by List).

Or you might create your own class with metods to iterate over rows or columns or all elements as needed.

Rasmus Kaj
  • 4,224
  • 1
  • 20
  • 23
0

I'm personally using the Vector class for that purpose, though different requirements may eventually dictate the use of other, more specialized classes.

moritz
  • 2,448
  • 1
  • 20
  • 25
  • Vector is pretty much deprecated and has been replaced by ArrayList. – Yoni Jan 12 '10 at 16:44
  • 2
    @mortiz - `java.util.Vector` should generally be avoided - its thread safety isn't very useful for most multi-threaded scenarios and just adds overhead to single-threaded usage. Most people use `ArrayList` as their default `List` type instead. – McDowell Jan 12 '10 at 16:44
0

java.util.ArrayList is my preferred choice.

http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html

Ben Hanzl
  • 45
  • 1
  • 5
  • I think it is used when we want to have dynamic 1-D array – Amit Jan 12 '10 at 16:35
  • You can have an ArrayList that each of its element would be another ArrayList (as rsp and me are proposing in our answers). In this way, an ArrayList can be used for 2D arrays as well. – Alex Ntousias Jan 12 '10 at 16:44
0

Import java.util.ArrayList;

ArrayList is what you want, you don't need to set up its size at creation time and you can add elements dynamically using the add method.

Alexander Derck
  • 13,818
  • 5
  • 54
  • 76
sap
  • 1,188
  • 1
  • 14
  • 25
0

It depends on what you're trying to do, but I would recommend ArrayList. It's faster than Vector. Unless you care about synchronization! If you want it as a 2-dimensional list, then you create an ArrayList and each element of this list would be another ArrayList.

Alex Ntousias
  • 8,962
  • 8
  • 39
  • 47
0

You could do a trial with an ArrayList having ArrayLists as items. If that doesn't do what you want, it will give instight in what you need to built yourself.

rsp
  • 23,135
  • 6
  • 55
  • 69
0

It depends on the way you want to use the data structure. Your options are:

  • Two lists; it's your job to synchronize between them.
  • A map; instead of a key-value relationship, your map entries will simply be tuples of objects.
  • A list of 2-cell object arrays; each item in the list will be an object array of size 2.

EDIT: I completely misread the question; I thought it was about a 2D array of width 2.

Having properly read the question (I hope :-)), I agree with those who said list-of-lists.

Eli Acherkan
  • 6,401
  • 2
  • 27
  • 34