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];
Related
What it comes down to is I'm attempting to construct a List<T> from the java.util.List package based on an enumerator, but here's the catch- I don't want the first value to be in the list. The way that I've come up with doing this... Well... It can't be a good thing.
Here's the code I'm using:
Arrays.asList(Arrays.asList(MyEnum.values()).remove(0));
This effectively creates a List<> from my enum, and removes the first value, then tries to create another list with the created list.
This may actually be the correct way to do it, but just looking at it is screaming "Inefficient". I showed it to a few people on a forum that I'm a member of and they all said how ugly it was, and laughed; However not a single one of them could/would provide a better way to go about doing it.
I don't think that code is really ugly or inefficient. The bigger problem is it doesn't work because the list returned by Arrays.asList is backed by the underlying array, and so it has a fixed size.
You can use subList instead of remove to get it working:
List<MyEnum> list = Arrays.asList(MyEnum.values());
list = list.subList(1, list.size());
This means that the resulting list actually consists of two list objects (the asList and its subList), which may or may not bother you. However, you can create a flat ArrayList from the resulting list:
list = new ArrayList<>(list);
If you'd rather minimize object allocation, loop the values and add them to a single list directly:
MyEnum[] values = MyEnum.values();
List<MyEnum> list = new ArrayList<>(values.length - 1);
for (int i = 1; i < values.length; i++)
list.add(values[i]);
How about:
Arrays.asList(MyEnum.values()).subList(1, MyEnum.values().length);
Are you sure you can't (wouldn't want to) use MyEnum.values and treat your first element differently where it's used?
public enum Enums {
first,
b,
c,
d,
e,
f;
public boolean isFirst(Enums e) {
return e == first;
}
}
This would work:
List<T> enums = Arrays.asList(Arrays.copyOfRange(MyEnum.values(), 1, MyEnum.values().length - 1));
Or java 8:
Arrays.stream(MyEnum.values()).collect(Collectors.toList()).subList(1, MyEnum.values() - 1);
Hmmm... not much better .
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);
This is what I have right now:
public ArrayList subList(int fromIndex, int toIndex){
ArrayList a = new ArrayList();
for (int i=fromIndex;i<toIndex;i++) {
a.add(stuff[i]); //stuff is a array of strings
}
return list;
}
But is it possible to return the sublist without creating a new array? I am restrict from using any methods from the Array/ArrayList class.
If you want have the same behaviour as the Java subList method you need to retain a pointer to the original list and use an offset and length to index into the original list.
Heres a start showing the implementation of the get method.
public class SubList extends AbstractList {
private final List original;
private final int from;
private final int to;
public SubList(List original, int from, int to) {
this.original = original;
this.from = from;
this.to = to;
}
public Object get(int i) {
if (i < 0 || i > to - from) {
throw new IllegalArguementException();
}
return original.get(from + i);
}
}
public static List subList(List original, int from, int to) {
return new SubList(original, from, to);
}
To avoid creating a new list for storage, you would have to pass in a reference to the original list, keep the sublist, and then delete the remaining items from from the list, but this would leave the list missing those other items.
If that isn't your goal you will have to create a new list at some point to hold the sublist.
I assume you have to return the standard ArrayList, and not your own version of ArrayList, and I assume that 'stuff' is an array, not a list.
First off, get bonus points for making the ArrayList have the initial size of the array (toIndex - fromIndex). For more bonus points, make sure that the to and from indecies actually exist in 'stuff' otherwise you get a nice crash.
ArrayList uses an internal array for its storage and you can't change that so you have no choice but to create a copy.
EDIT
You could make things interested and much more complex but it'll impress someone... Do it by creating your own ArrayList class implementing List. Get it to use that original array. Pretty unstable since if that array is modified somewhere else externally, you're in trouble, but it could be fun.
There's three sensible things you could return. An array, a List, or an Iterator. If my assumption that you're supposed to re-implement subList was correct, then there's no way around creating the new ArrayList.
A sublist is "a new list", so you'll have to create something to represent the sublist of the array. This can either be a new array or a list. You chose an ArrayList which looks good to me. You're not creating a new array (directly), so I don't actually get that point of your question. (If you want to avoid creating a new array indirectly through ArrayList, choose another List implementation, LinkedListfor example)
If you're looking for slight improvements:
Consider passing the source array as a method parameter. Now stuff[] is a static field.
Consider initializing the new ArrayList with the size of the sublist (toList-fromList+1)
Consider using generics (only if you already now this concept). So the return type would be ArrayList<String>
I have a hashMap. Each "Value"is going to be a a list which will be mapped later on with my "Key"s. List is desired to look like this:
[length,time][length,time][length,time]
For example:
Key{srcAddr=x, dstAddr=y, srcPort=12345, dstPort=80}
value{(6523,0.001),(124,0.05), () , (), ...}
I just wonder how can I have a two-col arrayList.
package myclassifier;
import java.util.ArrayList;
public class FlowStatics {
int packetLength;
double timeArrival;
public FlowStatics(int pLength, double tArrival)
{
this.packetLength = pLength;
this.timeArrival = tArrival;
}
}
and here is how I used it:
final ArrayList<FlowStatics> staticsArray = new ArrayList<FlowStatics>();
final HashMap<Flows, ArrayList> myHashMap = new HashMap<Flows, ArrayList>();
FlowStatics flowStatics = new FlowStatics(packetLength,timeArrival);
staticsArray.add(flowStatics);
myHashMap.put(flows, staticsArray);
and here is the part that I am reading it:
Iterator<Flows> iterator = myHashMap.keySet().iterator();
while(iterator.hasNext()){
Flows key = iterator.next();
ArrayList value = myHashMap.get(key);
System.out.println("Fows"+key+"----------"+"Statics"+ value);
Well, your FlowStatics is the correct solution
List<FlowStatics> will give you the "two-column array list".
Update: as of your update, myHashMap.put(flows, flowStatics); is wrong. You are this putting an individual pair, rather than a list in the map. You should use:
staticsArray.add(flowStatics);
myHashMap.put(flows, staticsArray);
A List<E> is an abstraction for a homogeneous list of elements whose type is E. There are some restrictions (e.g. no primitives), but conceptually the type E can be defined to be whatever you want.
Suppose there's an abstraction of Pair<L,R>. Then a List<Pair<L,R>> is still a list of some E, but now that E is a Pair<L,R>. So it's still a "one-column" list, but each element in the list is a "pair", so it's sort of a "two-column" list.
Note that you don't always need a generic Pair<L,R>. Any type E that properly encapsulates all the information can be used in a List<E>.
And by the way, you can have a List<List<E>> too.
See also
Wikipedia/Encapsulation
Related questions
What is the equivalent of the C++ Pair<L,R> in Java?
List of Lists of Lists
Returning values analogy
Often people ask "How can I return two values in Java?". The answer is analogous. You return one value, a new type which encapsulates both information.
So instead of:
// attempt to return two values
// DOES NOT COMPILE
return "James Bond";
return "007";
You do:
return new SecretAgent("James Bond", "007");
Related questions
Using a java method to return multiple values?
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.