I am building a simple 2D game in Java, but I cannot decide how to store the map data. I want something like arrays, however global arrays in Java are static, and they cannot be dynamic sized. I am going to load the map from a file, however, sometimes the maps are differently sized.
Hashmap looks too complicated for what I want. What would be a good way to store the data easily? I want to create a simple method to retrieve the data for each coordinate.
Example:
int blockdata = blockCheck(5, 8);
It would then return the data "5a7" or whatever the data is. In similar games I have just had static variables in an array, but I do not know how to do this being dynamically sized.
Generally I would recommend creating a custom Map class, that encapsulates the storage in private members. That way, if you change the internal storage, the rest of your code can still work unchanged. You can give the Map a nice APi so you can do stuff like map.get(10,12) and map.set(3,4,BRICK_WALL); etc.
For the internal storage you have a few choices / techniques to choose between:
Use nested data structures: an ArrayList of ArrayListss is fine to represent a 2D map, and allows for dynamic resizing
Use an existing lower-level library that provides 2D Map storage
Use nested arrays like Tile[][] or similar. If you want to create a new map, you'll need to create a new nested array of course, but this is generally not a problem.
Use a flat array Tile[] or similar, and compute index locations into this array. You can compute unique indexes with something like array[x + y * columnCount].
Personally, I'd probably go for arrays. They are the most lightweight and efficient, and I think dynamic sizing is generally unnecessary: if you need maps of different sizes just create a new Map of the required size each time.
I want something like arrays, however global arrays in Java are static, and they cannot be dynamic sized. I am going to load the map from a file, however, sometimes the maps are differently sized.
You can add a class member and initialize it with dynamic value in the constructor i.e. when you create it's object
class Map {
int[][] twodspace;
Map(){}
Map(int len, int width){
twodspace = new int[len][width];
}
}
You could have an ArrayList of ArrayLists. For example:
ArrayList<ArrayList<Integer>> myarray= new ArrayList<>();
int blockCheck(int x, int y) {
return myarray.get(x).get(y);
}
I am using a data structure based on tree maps, mainly because it's relatively sparse in my case and I need to be able to iterate in order:
public class Grid<T> implements Iterable<T> {
private TreeMap<Integer,TreeMap<Integer,T>> data = new TreeMap<Integer,TreeMap<Integer,T>>();
public T get(int row, int col) {
TreeMap<Integer,T> r = data.get(row);
return r == null ? null : r.get(col);
}
public void set(int row, int col, T value) {
TreeMap<Integer,T> r = data.get(row);
if (r == null) {
r = new TreeMap<Integer, T>();
data.put(row, r);
}
r.put(col, value);
}
}
I'd recommend to have a similar level of abstraction (your own 2d "Grid" backed by whatever data structure that suits your needs best), so you can easily tweak the underlying implementation (array, tree, hasmap, whatever) based on your needs without having to change the rest of the application code.
I just used a txt file with structure like this:
*
* + +
* ____
*
**************************
And then I was just processing the file. Simplest way there was for me. Then for example + character is something, - is something etc.
Related
Let's say we have a function with the following prototype:
public static funWithMatrices(int[][] aux)
Now, we could do:
int i = aux.length;
To get the number of rows in aux. Similarly, we could then do:
int j = aux[i].length;
To just get the length of each column. But is there a better way to do this? Of course, the compiler can't possible know that what you're passing is a matrix rather than an arbitrary array with differing row/column lengths, but is it possible to constrain it somehow?
I'd be more interested in something that's already built-in rather than creating my own matrix object with the given constraints. Though that'd be easy to do, it's not quite what I'm asking.
Sneak edit: I realize there is also the possibility of redefining the prototype to something like int[][] aux, n, m, but that is also not quite what I'm asking.
You can leverage object oriented programming nature of Java and create your own Matrix class with getColumnLength() and getRowLength() methods defined, or even better have a look at Apache Commons Math libraries and leverage existing Matrix API classes and functions
There is also la4j library that can be used as following:
public static void funWithMatrices(Matrix aux) {
int rows = aux.rows();
int columns = aux.columns();
// do what you want with matrix
// for example multyply each cell by 2 if it's symmetric matrix
if (aux.is(Matrices.SYMMETRIC_MATRIX)) {
Matrix aux2 = aux.transform(Matrices.asMulFunction(2.0));
}
}
// a caller
funWithMatrices(new Basic2DMatrix(new double[][]{
{ 1.0, 2.0 },
{ 3.0, 4.0 }
}));
I want to create a large matrix (n by n) where each element corresponds to a LinkedList (of certain objects).
I can either
Create the n*n individual linked lists and name them with the help of eval() within a loop that iterates through both dimensions (or something similar), so that in the end I'll have LinkedList_1_1, LinkedList_1_2 etc. Each one has a unique variable name. Basically, skipping the matrix altogether.
Create an ArrayList of ArrayLists and then push into each element a linked list.
Please recommend me a method if I want to conserve time & space, and ease-of-access in my later code, when I want to reference individual LinkedLists. Ease-of-acess will be poor with Method 1, as I'll have to use eval whenever I want to access a particular linked list.
My gut-feeling tells me Method 2 is the best approach, but how exactly do I form my initializations?
As you know the sizes to start with, why don't you just use an array? Unfortunately Java generics prevents the array element itself from being a concrete generic type, but you can use a wildcard:
LinkedList<?>[][] lists = new LinkedList<?>[n][n];
Or slightly more efficient in memory, just a single array:
LinkedList<?>[] lists = new LinkedList<?>[n * n];
// Then for access...
lists[y * n + x] = ...;
Then you'd need to cast on each access - using #SuppressWarnings given that you know it will always work (assuming you encapsulate it appropriately). I'd put that in a single place:
#SuppressWarnings("unchecked")
private LinkedList<Foo> getList(int x, int y) {
if (lists[y][x] == null) {
lists[y][x] = new LinkedList<Foo>();
}
// Cast won't actually have any effect at execution time. It's
// just to tell the compiler we know what we're doing.
return (LinkedList<Foo>) lists[y][x];
}
Of course in both cases you'd then need to populate the arrays with empty linked lists if you needed to. (If several of the linked lists never end up having any nodes, you may wish to consider only populating them lazily.)
I would certainly not generate a class with hundreds of variables. It would make programmatic access to the lists very painful, and basically be a bad idea in any number of ways.
can anyone tell me the error in this java declaration String[][] t=new String[15][15]; this works fine and if i use String[][] t=new String[][]; because i need to declare the variable t as dynamic as i am not sure how much values i am going to store in t.
Use ArrayList (or other array object who can handle any number of objects). A java array always has a fixed length since some memory will be reserved for the array.
ArrayList creates such array as well to store the objects. Of you add more abjects as the current reserved size of the array than ArrayList will create a new bigger array (+50% if i'm correct). There are some other implementations that act a bit different (for example they create a new array 100% of the original one when the array is full. If performance is really important for you than you can look into this.
ArrayList<ArrayList<String> t = new ArrayList<ArrayList<String>();
void fill() {
ArrayList<String> t2 = new ArrayList<String>();
t2.add("somestring");
String s = "someotherstring";
t2.add(s);
t.add(t2);
}
If you don't know how big it needs to be just declare it as
String[][] t;
and once you know how big it needs to be you can do (before trying to use the array)
t = new String[15][15];
If you're never sure how big the array need to be, you'll need to use something like a List of Lists.
List<List<String>> t = new ArrayList<List<String>>;
public void add(String str, int row, int col) {
while (row >= t.size())
t.add(new ArrayList<String>());
List<String> row_list = t.get(row);
while (col >= row_list.size())
row_list.add("");
row_list.set(col, str);
}
In Java array objects are always of fixed length. Once you have allocated them you cannot change their size. An array variable can be made to point to different array objects of different size. So you can allocate:
String[][] t;
which doesn't point to an object and allocate an object later once you know the size:
int n1,n2;
// calculate n1,n2
t = new String[n1][n2];
If you need a structure where the size can change you are much better off using ArrayList, which can be dynamically resized.
Declare it as String [][]t = null;
And Reinitialize it with actual length once you get it.
t=new String[x][y];
As bemace said, just because you are declaring the variable doesn't mean you have to initialize it immediately.
As Mark said, arrays have a fixed size. Once an array is initialized(not declared, initialized) it has a fixed size.
So, there are two possibilities:
Either you will know how big the array needs to be before you need to start using it, in which case you can simply delay your initialization as suggested by bemace.
Or you won't know how big it needs to be before you start using it, in which case you need to use a dynamically sized data structure(s). Check out the Java Collections API:
tutorial
api reference
There are several good answers already, but it has now been revealed in a comment to Mark Baijens' answer that the purpose of this question is that raju need a key to multi-value mapping.
Mark followed up that comment by suggesting raju use a HashMap<String, String> hashMap = new HashMap<String, String>(); — however that only works for a single key-value pair.
What raju needs is a
Map<String, Collection<String>> t
= new HashMap<String, List<String>>();
Adding the first value for a key requires initialization of a List for that bucket, while adding additional values requires fetching the existing list and adding the new value.
Note I used Collection<String> in the declaration, so it could be a List if the order of values is important, or it could be a Set to prevent duplicate values under the same key.
This would probably be best implemented as a Class itself, perhaps
public class MultiValueMap<K, V> extends Map<K, V>
{
...
}
so the initialization of the List on the first put(key, value) and the subsequent .add(value) to the list could be hidden in the implementation.
how can I create an array of tuples in jsp (java)
like
(a:1, b:2)
(c:3, d:4)
...
...
Create a tuple class, something like:
class Tuple {
private Object[] data;
public Tuple (Object.. members) { this.data = members; }
public void get(int index) { return data[index]; }
public int getSize() { ... }
}
Then just create an array of Tuple instances.
if you want an arbitrary size tuple, perl hash style, use a Map<K,V> (if you have a fixed type of keys values - your example looks like Map<Character,Integer> would work - otherwise use the raw type). Look up the java collections for more details about the various implementations.
Given those tuples, if you want to stick them in an sequential collection, I'd use a List (again, look up the collections library).
So you end up with
List<Map<K,V>> listOfTuples
if you need something more specific (like, you'll always have x1, x2, x3 in your tuple) consider making the maps be EnumMaps - you can restrict what keys you have, and if you specify a default (or some other constraint during creation) guarantee that something will come out.
There's no default pair / n-tuple class in Java; you'd have to roll your own.
you could use the HashSet class.
If you are dealing with tuples of fixed size, with fixed names of the attributes, define a simple data class of your own, and then define the array of this class.
If on the other hand you want the attribute names to be flexible and determined at runtime, use a Map structure. In your example above, it seems like HashMap<String,Integer> can do the job. You may want to wrap it in order to reduce its functionality, and maybe also add more specific functionality.
I know I am late to the party but an array of points should do the job.
Check here to see the documentation about points.
which is the best way to write a bidimensional hashmap efficiently in Java? Just to give an example of what I'm talking about: I'm developing some algorithms related to collective intelligence, these algorithms works by calculating correlation between pairs of elements..
Without caching these values, since they are calculated on same pairs multiple times, performance are horrible.. (algorithms can be O(n^2) but maybe O(n^3) so I was thinking about using an HashMap to store values to be used multiple times.
Which is the most efficient way to implement such a data structure in Java? It should be possble to cache and remove a value generated by a pair of elements with O(1), but using an explicit class seems too heavy anyway.
If Java will turn out to be not enough I'll have to switch to C/C++, so any idea related to these languages are welcome too.
Thanks
The easiest way to do this is to define a Pair class. It should be immutable (hash keys should not change), and hashCode() should be consistent with equals.
Something like (method implementations omitted):
public class Pair() {
int a, b;
public Pair(int a, int b);
public int getA();
public int getB();
public boolean equals(Object obj);
public int hashCode();
}
Notes:
If you don't want ints, sub in whatever type you want, or make your Pair class generic if you want it to be flexible.
It would be up to you whether (x, y) == (y,x).
With this in hand, you can have a HashMap<Pair, SomethingElse> as your cache.
I partially solved the problem by concatenating hashcodes of both items using something like this:
private long computeKey(Object o1, Object o2)
{
int h1 = o1.hashCode();
int h2 = o2.hashCode();
if (h1 < h2)
{
int swap = h1;
h1 = h2;
h2 = swap;
}
return ((long)h1) << 32 | h2;
}
I still have to figure out which is the most efficient way to store all the elements already cached with a specified one to remove them when the algorithm don't need the item anymore, just to avoid filling of the HashMap with a waste of item. That's because the kind of algorithm merges two items at every iteration removing them from used ones but adding the new generated item.
Google Collections supports bi-directional hashmaps, see BiMap.
(BTW, Google Collections seems to be gaining more mindshare over Apache Collections.)
Update: Note #danben and #sateesh's clarification. A BiMap would be fine if you need to get a y given an x, or an x given a y. But it sounds like you really want to look up an (x, y) point and get back a value that contains your cached information. In that case, go with #danben's suggestion.