Multidimensional Arrays in Java - java

Alright, so I've been working with PHP for most of my career and find myself needing to use Java. In my case, the biggest issue I have is creating and manipulating arrays in Java.
Example in PHP:
$cars = array(1 => array("stats"=> array("velocity"=>100,
"acceleration"=>0,
"energy"=>30000,
"distance"=>200
)
),
2 => array("stats"=> array("velocity"=>3,
"acceleration"=>6,
"energy"=>30000,
"distance"=>200)
)
);
I'm trying to re-create this type of array in Java but I'm having trouble with initializing it. Is the array considered a String in this case? And must the size of the array be set prior to creating it? e.g: String[][][] car = new String[][][]?

Exactly as aet said in a comment - if you're considering doing this in java - don't. You're doing it wrong.
You should have a class for Car
public class Car {
private int velocity;
private int acceleration;
private int energy;
private int distance;
//getters and setters, a constructor that gets all the property values ...
}
and then store your cars in some collection. An ArrayList is the easiest way:
List<Car> cars = new ArrayList<Car>();
cars.add(new Car(100,0,30000,200));
cars.add(new Car(3,6,30000,200));
Accessing the list of cars would then look like this:
cars.get(0).getVelocity(); //collection indexes start at 0

I think Java doesn't have TRUE multidimensional arrays. An array which is accessed like a[i][j][k] is simply an array, of arrays, of arrays.
You can try the following construct:
String[][] car = new String [][] { { "X0", "Y0"},
{ "X1", "Y1"},
{ "X2", "Y2"},
{ "X3", "Y3"},
{ "X4", "Y4"} };

1) is that "stats" index nesserly? if not, you can:
Map<String, Integer>[] cars = new HashMap<String, Integer>[your length here];
this will index your cars by numbers, skip the "stats" index, and allow you to index the last integer by string:
int velocityOfSecondCar = cars[1].get("velocity"); //note indexing from 0
2) if "stats" index is nesserly, you would have to go one dimension deeper

What you have in PHP there would typically be represented as nested Map instances in Java. For example:
HashMap<Integer,Map<String,Map<String,Integer>>> data = new HashMap<>();
Then you could get values (assuming all levels of the Hash are populated correctly) by saying:
int velocity = data.get(1).get("stats").get("velocity");
Populating nested maps like this can be complicated, and you would typically use a helper method to make sure all the 'parent' levels are populated before you add a data member.

Yes, lenghts must be provided when initializing an array. Hence, your array would look something like this:
int lenght1=x;
int length2=y;
int lenght3=z;
String[][][] car = new String[lenght1][lenght2][lenght3]
I'm no PHP developer myself, but Classes within the array will obey the OOP rules Java implements in terms of abstraction and inheritance. So when you retrieve the elements you can use their corresponding interfaces whatever the class or interface that contains them are.
On the other hand, if you can't know the array lenghts before the initialization you can use class ArrayList, which is almost like a Vector. This class modify its internal length if new elements are added. Along with ArrayList you have a complete set of data structures in the Java specs to store the elements, like Maps, Sets, Lists, etc...
When instantiating an ArrayList you should specify which class or interface will describe the objects you are storing within the data structure, so you'll have to use generics to instantiate the structure. In your case:
ArrayList<String> dim1=new ArrayList<String>();
ArrayList<ArrayList<String>> dim2=new ArrayList<ArrayList<String>>();
ArrayList<ArrayList<ArrayList<String>>> dim3= new ArrayList<ArrayList<ArrayList<String>>>();
As you can see this structure is way sexier than the simple arrays above, but obviusly will require more care to deal with it. Don't forget to instantiate your arraylists before putting them in your 3d matrix, or you'll get an exception later for accesing a null objects.

try this..
Map<Integer, HashMap<String, HashMap<String, Integer>>> map = new HashMap<>();
HashMap<String, Integer> hm = new HashMap<>();
hm.put("Velocity", 1);
hm.put("acceleration", 2);
HashMap<String, HashMap<String, Integer>> state1 = new HashMap<>();
state1.put("state1", hm);
map.put(1, state1);
System.out.println(map);

Related

Convert Multiple Arrays to one big multidimesional array and how to manipulate it

So I have these four arrays
ArrayList<String> names = new ArrayList<>();
ArrayList<String> licensePlates = new ArrayList<>();
ArrayList<Integer> mileage = new ArrayList<>();
ArrayList<Integer> engineHours = new ArrayList<>();
But returning them one by one is a hassle so I was wondering how I would go about making a multi-dimensional array to hold all these values instead. And also how I would go about adding something to them, for example, let's say I wanted to add an extra licence plate to the licence plate part of the multi-dimensional array.
Make a class. It is really a bad idea to try to shoehorn lists with different meanings into one big multidimensional list, or to try to have multiple lists "line up" like that.
class Car {
String name;
String licensePlate;
int mileage;
int engineHours;
...constructor, getters...
}
List<Car> carList;
I would highly recommend louis-wasserman approach of creating a class.
If you are looking for an alternative then you can take a look at Guava's ListMultiMap
ListMultiMap<String, Object> multiDimArray = ArrayListMultiMap.create();
multiDimArray.put("names", "merc");
multiDimArray.put("mileage", 10);
multiDimArray.put("names", "bmw");
multiDimArray.put("mileage", 20);
// To retrieve the names lists:
List<String> names = multiDimArray.get("names");

how can we add (long,String) in arraylist?

I need to create a list with values of type - (long,String)
like -
ArrayList a = new ArrayList();
a.add(1L,branchName);
How can I do this because if I use list It will accept only int,String.
You should note that ArrayList's add(int,String) adds the String element in the given int index (if the index is valid). The int parameter is not part of the contents of the ArrayList.
Perhaps an ArrayList is not the correct choice for you. If you wish to map Long keys to String values, use Map<Long,String>.
Map<Long,String> a = new HashMap<> ();
a.put(1L,branchName);
You can define a custom class, e.g.
class IndexAndBranchName {
long index;
String branchName;
}
and then add instances of this to the ArrayList:
ArrayList<IndexAndBranchName> a = new ArrayList<>();
a.add(new IndexAndBranchName(index, branchName));
Whether you use this approach or something like Eran's depends upon what you need to use the list for subsequently:
If you want to look "branches" up by index, use a Map; however, you can only store a single value per key; you could use a Guava Multimap or similar if you want multiple values per key.
If you simply want all of the index/branch name pairs, you can use this approach.
You can use the below code for your question.
HashMap is also a better option , but if you want only ArrayList then use it.
List<Map<Object, Object>> mylist = new ArrayList<Map<Object, Object>>();
Map map = new HashMap<>();
map.put(1L, "BranchName");
mylist.add(map);

How to make two dimensional LinkedList in java?

for example:
public static LinkedList<String, Double> ll = new LinkedList<String, Double>;
from your question, I think (not 100% sure) you are looking for
java.util.LinkedHashMap<K, V>
in your case, it would be LinkedHashMap<String, Double>
from java doc:
Hash table and linked list implementation of the Map interface, with
predictable iteration order. This implementation differs from HashMap
in that it maintains a doubly-linked list running through all of its
entries.
if you do want to get element by list.get(5), you could :
LinkedList<Entry<String, Double>>
so you can get Entry element by Entry entry = list.get(5), then entry.getKey() gives you the STring, and entry.getValue() gives you the Double.
Reading all your comments, I suggest you do something like this:
public class StringAndDouble {
private String str;
private double dbl;
// add constructor
// add getters, setters and other methods as needed.
// override equals() and hashCode()
}
Now you can use:
List<StringAndDouble> list = new LinkedList<>(); // or
List<StringAndDouble> list = new ArrayList<>(); // better in most cases
Now you can access your objects by index.
This answer creates a new class, to fit your needs. The class has two fields, one String, one double. This doesn't make the class two dimensional. I think you have a misunderstanding there. When there are n dimensions, you need n indexes to access an element. You were talking of accessing by index, so I assume you're looking for a one dimensional list holding the objects, that have more than one field.
Do you mean like this?
HashMap<String, Double> hm = new HashMap<String, Double>();
Since OP in a comment to #Kent says he wants to be able to get items by index...
Note that a LinkedList (and LinkedHashMap) are inefficient at that. He may prefer an ArrayList. So I would suggest that his "2D" implementation be a
ArrayList<Map.Entry<String, Double>>
which will efficiently support a get by index.
As for the normal get(String key), you'd have to do a linear search of all the entries, which would be inefficient.
So, you have a decision: which way of accessing (by a key or by an index) is more important?
You can actually use Linked Lists within eachother...
For Example:
public LinkedList<LinkedList<Integer>> twoDimLinkedList = new LinkedList<LinkedList<Integer>>();
Then:
////////////////
int value = twoDimLinkedList.get(3).get(4);
/////////////////
or (If you were planning on using it for iterative purposes):
/////////////////
for (int i = 0; i < twoDimLinkedList.size(); i++) {
LinkedList<Integer> twoDimLinkedListRow = new LinkedList<Integer>();
for (int m = 0; m < twoDimLinkedList.get(i).size(); m++) {
twoDimLinkedListRow.add(value);
}
twoDimLinkedList.add(twoDimLinkedListRow);
}
////////////////

How to implement a 2d array of LinkedLists

I'm working on implementing an algorithm from a paper. The paper describes using a grid, where each grid square holds a linked list of integers that represent objects in that grid square.
I decided to implement this using LinkedList<Integer>[][], which of course gives me a generic array creation error.
I can't think of a better way of representing the idea of a grid of linked lists. I also understand that using LinkedList[][] would compile but is bad practice as it is untyped. However, I would prefer not to use ArrayList<ArrayList<LinkedList<Integer>>> because that is unreadable, at least to me.
Is there a way around using an untyped LinkedList here? Or perhaps some other solution?
The list version
List<List<List<Integer>>> grid;
is not unreadable. To access a grid square it's just
List<Integer> items = grid.get(x).get(y);
Not that tough on the brane.
Bohemian's answer is on the mark. If you're using Guava, a possible alternative is to use an ArrayTable<Integer, Integer, List<Integer>>. From the documentation:
Fixed-size Table implementation backed by a two-dimensional array.
The allowed row and column keys must be supplied when the table is
created. The table always contains a mapping for every row key /
column pair. The value corresponding to a given row and column is null
unless another value is provided.
The table's size is constant: the product of the number of supplied
row keys and the number of supplied column keys. The remove and clear
methods are not supported by the table or its views. The
erase(java.lang.Object, java.lang.Object) and eraseAll() methods may
be used instead.
Here's an example of its usage:
private static final int NUM_ROWS = 20; //for example
private static final int NUM_COLS = 20; //
private static final ArrayTable<Integer, Integer, List<Integer>> TABLE =
ArrayTable.create(
Ranges.closed(1, NUM_ROWS).asSet(DiscreteDomains.integers()),
Ranges.closed(1, NUM_COLS).asSet(DiscreteDomains.integers())
);
public static List<Integer> getGridQuareList(int row, int col) {
#Nullable List<Integer> list = TABLE.at(row, col);
if (list == null) {
list = Lists.newArrayList(); //or newLinkedList() if you insist
TABLE.set(row, col, list);
}
return list;
}
I would use the embedded ArrayList/LinkedList. What you can do to clean it up, since you know what kind of generic type they will have, is to wrap them inside some other class. Like so:
public class Grid {
private List<List<List<Object>>> inner;
public List<Object> objectsAtPosition(int x, int y) {
return inner.get(x).get(y);
}
// etc
}
I don't know why on earth you would need a 3 dimensional list (2d array of a list, considering ArrayLists is really a 3d list/array). But if you do need that, then you should use what #Bohemian wrote:
List<List<List<Integer>>> grid;
What you should consider:
Declare variables to interfaces, not implementations, eg.:
List<Integer> list = new ArrayList<Integer>
instead of
ArrayList<Integer> list = new ArrayList<Integer>
Also, generally it's not a good idea to mix generics with arrays, it can get nasty. If you wan't to do it in java and that's what you need do it the java way, as the others stated:
List<List<List<Integer>>>
You can declare an array of the linked list as follows.. but do not forget to declare when you are going to use the linked list otherwise you will get the nullpointeexception
LinkedList<Integer>[][] ll = new LinkedList[24][24];
ll[0][0] = new LinkedList<>();
ll[0][0].addFirst(3);
System.out.println(ll[0][0].removeFirst());
Output : 3
First: You proably can avoid LinkedList. In Algorithm books, they did not know the ArrayList, Linked List, is more a synonym for dynamic list.
In nearly all cases ArrayList is faster, and especially for 2D arrays, need much less memory.
I personaly when having a fixed grid, with dynamic content, I use arrays:
List grid[][];
// init with
grid = new ArrayList[numX][numY];
that way i have an grid of object. This uses much less memory.
That way its is much handier when adding objetcs:
List list = grid[i][j];
if (list == null) {
list = new ArrayList();
this.cells[i][j] = list;
}
list.add(obj);
I decided to implement this using LinkedList[][], which of
course gives me a generic array creation error.
I can't think of a better way of representing the idea of a grid of
linked lists. I also understand that using LinkedList[][] would
compile but is bad practice as it is untyped.
Simple. To solve those problems just do
LinkedList<Integer>[][] grid = (LinkedList<Integer>[][])new LinkedList<?>[5][3];

Cannot create an array of LinkedLists in Java...?

I'm working on a sparse matrix class that needs to use an array of LinkedList to store the values of a matrix. Each element of the array (i.e. each LinkedList) represents a row of the matrix. And, each element in the LinkedList array represents a column and the stored value.
In my class, I have a declaration of the array as:
private LinkedList<IntegerNode>[] myMatrix;
And, in my constructor for the SparseMatrix, I try to define:
myMatrix = new LinkedList<IntegerNode>[numRows];
The error I end up getting is
Cannot create a generic array of LinkedList<IntegerNode>.
So, I have two issues with this:
What am I doing wrong, and
Why is the type acceptable in the declaration for the array if it can't be created?
IntegerNode is a class that I have created. And, all of my class files are packaged together.
For some reason you have to cast the type and make the declaration like this:
myMatrix = (LinkedList<IntegerNode>[]) new LinkedList<?>[numRows];
You can't use generic array creation. It's a flaw/ feature of java generics.
The ways without warnings are:
Using List of Lists instead of Array of Lists:
List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
Declaring the special class for Array of Lists:
class IntegerNodeList {
private final List< IntegerNode > nodes;
}
Aside from the syntax issues, it seems strange to me to use an array and a linked list to represent a matrix. To be able to access arbitrary cells of the matrix, you would probably want an actual array or at least an ArrayList to hold the rows, as LinkedList must traverse the whole list from the first element to any particular element, an O(n) operation, as opposed to the much quicker O(1) with ArrayList or an actual array.
Since you mentioned this matrix is sparse, though, perhaps a better way to store the data is as a map of maps, where a key in the first map represents a row index, and its value is a row map whose keys are a column index, with the value being your IntegerNode class. Thus:
private Map<Integer, Map<Integer, IntegerNode>> myMatrix = new HashMap<Integer, Map<Integer, IntegerNode>>();
// access a matrix cell:
int rowIdx = 100;
int colIdx = 30;
Map<Integer, IntegerNode> row = myMatrix.get(rowIdx); // if null, create and add to matrix
IntegerNode node = row.get(colIdx); // possibly null
If you need to be able to traverse the matrix row by row, you can make the row map type a TreeMap, and same for traversing the columns in index order, but if you don't need those cases, HashMap is quicker than TreeMap. Helper methods to get and set an arbitrary cell, handling unset null values, would be useful, of course.
class IntegerNodeList extends LinkedList<IntegerNode> {}
IntegerNodeList[] myMatrix = new IntegerNodeList[numRows];
myMatrix = (LinkedList<IntegerNode>[]) new LinkedList[numRows];
casting this way works but still leaves you with a nasty warning:
"Type safety: The expression of type List[] needs unchecked conversion.."
Declaring a special class for Array of Lists:
class IntegerNodeList { private final List< IntegerNode > nodes; }
is a clever idea to avoid the warning. maybe a little bit nicer is to use an interface for it:
public interface IntegerNodeList extends List<IntegerNode> {}
then
List<IntegerNode>[] myMatrix = new IntegerNodeList[numRows];
compiles without warnings.
doesn't look too bad, does it?
List<String>[] lst = new List[2];
lst[0] = new LinkedList<String>();
lst[1] = new LinkedList<String>();
No any warnings. NetBeans 6.9.1, jdk1.6.0_24
There is no generic array creation in Java 1.5 (or 1.6 as far as I can tell). See https://community.oracle.com/message/4829402.
If I do the following I get the error message in question
LinkedList<Node>[] matrix = new LinkedList<Node>[5];
But if I just remove the list type in the declaration it seems to have the desired functionality.
LinkedList<Node>[] matrix = new LinkedList[5];
Are these two declarations drastically different in a way of which I'm not aware?
EDIT
Ah, I think I've run into this issue now.
Iterating over the matrix and initializing the lists in a for-loop seems to work. Though it's not as ideal as some of the other solutions offered up.
for(int i=0; i < matrix.length; i++){
matrix[i] = new LinkedList<>();
}
You need an array of List, one alternative is to try:
private IntegerNode[] node_array = new IntegerNode[sizeOfYourChoice];
Then node_array[i] stores the head(first) node of a ArrayList<IntegerNode> or LinkedList<IntegerNode> (whatever your favourite list implementation).
Under this design, you lose the random access method list.get(index), but then you could still traverse the list starting with the head/fist node store in the type safe array.
This might be an acceptable design choice depending on your use case. For instance, I use this design to represent an adjacency list of graph, in most use cases, it requires traversing the adjacency list anyway for a given vertex instead of random access some vertex in the list.

Categories