Multidimensional arrays with different sizes - java

I just had an idea to test something out and it worked:
String[][] arr = new String[4][4];
arr[2] = new String[5];
for(int i = 0; i < arr.length; i++)
{
System.out.println(arr[i].length);
}
The output obviously is:
4
4
5
4
So my questions are:
Is this good or bad style of coding?
What could this be good for?
And most of all, is there a way to create such a construct in the declaration itself?
Also... why is it even possible to do?

Is this good or bad style of coding?
Like anything, it depends on the situation. There are situations where jagged arrays (as they are called) are in fact appropriate.
What could this be good for?
Well, for storing data sets with different lengths in one array. For instance, if we had the strings "hello" and "goodbye", we might want to store their character arrays in one structure. These char arrays have different lengths, so we would use a jagged array.
And most of all, is there a way to create such a construct in the declaration itself?
Yes:
char[][] x = {{'h','e','l','l','o'},
{'g','o','o','d','b','y','e'}};
Also... why is it even possible to do?
Because it is allowed by the Java Language Specification, §10.6.

This is a fine style of coding, there's nothing wrong with it. I've created jagged arrays myself for different problems in the past.
This is good because you might need to store data in this way. Data stored this way would allow you to saves memory. It would be a natural way to map items more efficiently in certain scenarios.
In a single line, without explicitly populating the array? No. This is the closest thing I can think of.
int[][] test = new int[10][];
test[0] = new int[100];
test[1] = new int[500];
This would allow you to populate the rows with arrays of different lengths. I prefer this approach to populating with values like so:
int[][] test = new int[][]{{1,2,3},{4},{5,6,7}};
Because it is more readable, and practical to type when dealing with large ragged arrays.
Its possible to do for the reasons given in 2. People have valid reasons for needing ragged arrays, so the creators of the language gave us a way to do it.

(1) While nothing is technically/functionally/syntactically wrong with it, I would say it is bad coding style because it breaks the assumption provided by the initialization of the object (String[4][4]). This, ultimately, is up to user preference; if you're the only one reading it, and you know exactly what you're doing, it would be fine. If other people share/use your code, it adds confusion.
(2) The only concept I could think of is if you had multiple arrays to be read in, but didn't know the size of them beforehand. However, it would make more sense to use ArrayList<String> in that case, unless the added overhead was a serious matter.
(3) I'm not sure what you're asking about here. Do you mean, can you somehow specify individual array lengths in that initial declaration? The answer to that is no.
(4) Its possible to extend and shrink primitive array lengths because behind the scenes, you're just allocating and releasing chunks of memory.

Related

Selection of Array depending on variable in Java

I am sure that this post silly, while I need still some practical ideas. I have 20 double[] arrays named like colVal1, colVal2,... Now I have 5 variables say que1, que2, que3, que4, que5 which contain integers from 1 to 20. I want to use arrays depending on the value contained in quei. Means if que1 contains 3 then I like to use colval3 in calculation. Manual use is avoidable due permutations of 20 numbers in 5 variables. Google hints that Java, in principle avoid replacement of variable name by another variable. I am lost at using HashMap. I could not use Reflection APIs correctly due to my limited knowledge base. Any handle is welcome.
Thanks and Regards
You know how to use an array I assume, so use an array of arrays.
double[][] colVal = new double[21][];
for (int i = 1; i <= 20; i++) {
double[] row = colVal[i];
System.out.println(Arrays.toString(row));
}
Note: this might be simpler if you started at 0 for the first row, instead of 1. i.e. you wouldn't need the unused row at the start.

Which Array / List should I use to keep an static index?

I usually use HashMap<Integer, Object> to keep an array of objects where you can get items by Integer.
I'm showing you an example so you can understand.
HashMap<Integer,String>:
[0] - Hello
1 - How are you doing
[2] - Bye
So with a HashMap, I can remove items avoiding the rest moving from their indexes.
hashmap.remove(0)
[0] - null
1 - How are you doing
[2] - Bye
But HashMap shouldn't be used for indexes with an Integer. So... Which kind of array should I use to perform actions like the ones I am explaining above?
Edit: About the part of "shouldn't be used", this is what Android Eclipse is telling me:
You can use a simple Array. They can be pointed by integer. And other than calling remove you can set null to the specific place. If you really want to call remove write your own wrapper method which does that for you.
I your indices are dense (no big holes in a range [0..n], the most efficient approach would be to use a plain array of String:
final String[] lup = new String[3];
lup[0] = "Hello";
lup[1] = "How are you doing";
lup[2] = "Bye";
// to remove elements just set the index to `null`:
lup[0] = null;
You can use SparseArray which is similar to HashMap<Integer,String>
SparseArray<String> arr=new SparseArray<String>();
arr.put(0, "Hello");
If you already know the total size, then go with Arrays. But if you don't then go with ArrayList.
Now, I don't see a purpose of mapping here.
Hashmap is a Map data structure. Like a list each item that is stored in a hashmap is stored at a particular index. This index is called a hash and it is generated using a hash function. Hash functions accept the object to be stored as an argument and generate a number that is unique to it. Different hashing functions have different trade-offs. A function that is too sparse will use up more space than required(your case). while one that is not sparse enough will suffer from collisions where objects use the same hash.
Further Reading if interested: Look at Android's SparseArray implementation for inspiration.
View the source by downloading AOSP's source code here http://source.android.com/source/downloading.html.
It is highly optimized for integers!
Actually, you can use a simple array of strings.
String arr[] = new String[size];
After reading a little bit, I guess the answer is the following:
1.- I can't use plain arrays. Reason: I might not know the final size of it.
2.- Lists doesnt fit, as when you remove an item, the following items fits to the new index. I don't want index move.
So as a global answer, using HashMap is OK, however using SparseArray is recommended as it is more efficient.

How to store table or matrix in Java?

I used to use matrix in octave to store data from data set, in Java how can I do that? Assume I have 10-20 columns and large data, I don't think
int [][]data;
would be the best option. Is nested map the only solution?
You could create a class Coordinate that takes an X and Y values and properly implement hashCode and equals.
Then create a HashMap<Coordinate, Data> and work with it.
Depends on what you need to do. If you know the size of the lists, then an array is definitely ideal since it means you will have instant access (read/write time) to any position in the array, this is very useful for speed.
Maps are better if you dont know the size and it needs to be able to adapt.
And finally, as I discovered in a previous question, if you have a TON of data, and a lot of it will be "0" you might want to also consider using a Sparse Martrix
This answer merges some of gnomed's answer and SJuan76's answer contents.
At a quick glance, I'd suggest you to use bidimentional arrays such as int[][].
It's not a very huge amount of data (we're speaking of ≈500 ints) so it's not a bad idea.
Advantages: It's the simpler, ideal (from the data-structuring side) way to go,
especially if every “slot” of the matrix contains data.
The inconvenient: You have to know the size of the matrix before constructing it.
Anyway, you can resize it later using the Arrays utilities.
If you want more effective handling of the data, you can use a single point-map.
That is, the key of every entry is a java.awt.Point that defines where is the value located.
Advantages: It's more effective than having a 2D array,
especially if part of your matrix doesn't contain data.
And it's adaptative; you don't need to know any sizes to construct/resize it.
The inconvenient: If every “slot” of your matrix contains data,
you'll loose (a lot of) space and performance. A 2D-array is more effective then.
Want more? If your data is really huge you can use a sparse matrix.
See this question for more details.
I would not discard multidimensional arrays so far: have you tried them? Are you finding specific limitations? IMHO as long as your data fits in memory, arrays can be good.
If your data is very sparse though, you may want to look at maps indeed.
Related question btw: Making a very large Java array
You can use multidimensional arrays or you can try any pairs like HashMap
I think multi-dimentional arrays are the best choice! They should serve your purpose. If your data set is only integers, int [] [] is an ideal choice.
Well, if your indices are small integers, you can certainly use nested arrays.
In a matrix class, you may want to use a plain array, like so: (assuming n is the number of columns)
double get(int i, int j) { return data[i*n + j]; }
For a general table (sparse matrix), you can use nested maps, but consider using com.google.common.collect.Table implementations from the Google Guava library.

Fastest way to access a table of data Java

Basically I am amidst a friendly code optimisation battle (to get the fastest program), I am trying to find a way that is faster to access a dictionary of hard coded data than a multidimensional array.
e.g to get the value for x:
int x = array[v1][v2][v3] ;
I have read that nested switch statements in a custom array may possibly be faster. Or is there a way I can possibly access memory more directly similar to pointers in C. Any ideas appreciated!
My 'competitor' is using a truth table and idea is to find something faster!
Many Thanks
Sam
If the array is regular in shape (i.e. MxNxK for some fixed M, N and K), you could try flattening it to achieve better locality of reference:
int array[] = new int[M*N*K];
...
int x = array[v1*N*K + v2*K + v3];
Also, if the entire array doesn't fit in the CPU cache, you might want to examine the patterns in which the array is accessed, to perhaps re-order the indices or change your code to make better use of the caches.

How do you (get around) dynamically naming variables?

I'm not sure if I'm using the right nomenclature, so I'll try to make my question as specific as possible. That said, I imagine this problem comes up all the time, and there are probably several different ways to deal with it.
Let's say I have an array (vector) called main of 1000 random years between 1980 and 2000 and that I want to make 20 separate arrays (vectors) out of it. These arrays would be named array1980, array1981, etc., would also have length 1000 but would contain 1s where the index in the name was equal to the corresponding element in main and 0s elsewhere. In other words:
for(int i=0; i<1000; i++){
if(main[i]==1980){
array1980[i]=1;
} else {
array1980[i]=0;
}
Of course, I don't want to have to write twenty of these, so it'd be good if I could create new variable names inside a loop. The problem is that you can't generally assign variable names to expressions with operators, e.g.,
String("array"+ j)=... # returns an error
I'm currently using Matlab the most, but I can also do a little in Java, c++ and python, and I'm trying to get an idea for how people go about solving this problem in general. Ideally, I'd like to be able to manipulate the individual variables (or sub-arrays) in some way that the year remains in the variable name (or array index) to reduce the chance for error and to make things easier to deal with in general.
I'd appreciate any help.
boolean main[][] = new boolean[1000][20];
for (int i=0; i < 1000; i++) {
array[i][main[i]-1980] = true;
}
In many cases a map will be a good solution, but here you could use a 2-dim array of booleans, since the size is known before (0-20) and continuous, and numerable.
Some languages will initialize an array of booleans to false for every element, so you would just need to set the values to true, to which main[i] points.
since main[i] returns numbers from 1980 to 2000, 1980-main[i] will return 1980-1980=0 to 2000-1980=20. To find your values, you have to add 1980 to the second index, of course.
The general solution to this is to not create variables with dynamic names, but to instead create a map. Exactly how that's done will vary by language.
For Java, it's worth looking at the map section of the Sun collections tutorial for a start.
Don Roby's answer is correct, but i would like to complete it.
You can use maps for this purpose, and it would look something like this:
Map<Integer,ArrayList<Integer>> yearMap = new HashMap<Integer,ArrayList<Integer>>();
yearMap.put(1980,new ArrayList<Integer>());
for (int i = 0; i < 1000; i++){
yearMap.get(1980).add(0);
}
yearMap.get(1980).set(999,1);
System.out.println(yearMap.get(1980).get(999));
But there is probably a better way to solve the problem that you have. You should not ask how to use X to solve Y, but how to solve Y.
So, what is it, that you are trying to solve?

Categories