_Al3x
|
 |
«
Posted
2012-03-17 19:11:16 » |
|
Hello guys!  I have a quick question, how do I do an array of ArraList? Something like: 1
| public ArrayList[] layers = new ArrayList(); |

|
|
|
|
UprightPath
|
 |
«
Reply #1 - Posted
2012-03-17 19:28:43 » |
|
Same way you would declare an array of any other type. 1 2 3 4
| ArrayList[] arrayOfArrayList = new ArrayList[size]; for(int i = 0; i < size; i++) { arrayOfArrayList[i] = new ArrayList(); } |
However, if you're planning on using the Generic functionality of the ArrayList (ArrayList<SomeOtherClass>) you cannot use an array of arraylists for it. :3
|
|
|
|
_Al3x
|
 |
«
Reply #2 - Posted
2012-03-17 19:33:23 » |
|
Thanks UprightPath for your quick answer  , however I have some issues: I have something like this: 1 2 3 4 5 6 7 8 9
| public ArrayList[] ArrayOfArrayList = new ArrayList[4]; ... ...
if (ArrayOfArrayList[0].isEmpty()){ ... ... ... } |
What I'm doing wrong? 
|
|
|
|
Games published by our own members! Check 'em out!
|
|
UprightPath
|
 |
«
Reply #3 - Posted
2012-03-17 19:38:48 » |
|
That's what the: 1 2 3
| for(int i = 0; i < size;i++) { arrayOfArrayLists[i] = new ArrayList(); } |
Takes care of. After you initialize the array, you then have to initialize the objects in the array. An array is just a data structure, something that holds data. Until you assign data to the elements in the array (arrayOfArrayList = something), the values are always going to be null. An array doesn't (really) care what sort of object is placed in it. It doesn't do anything special. It won't fill itself in with default values (Unless it's a primitive array, and even then it's best not to assume).
|
|
|
|
_Al3x
|
 |
«
Reply #4 - Posted
2012-03-17 19:51:56 » |
|
Thank you very much! That was very clear!  I thought that public ArrayList[] ArrayOfArrayList = new ArrayList[4]; was already initializing every element! Thank you again! 
|
|
|
|
ra4king
|
 |
«
Reply #5 - Posted
2012-03-17 20:08:28 » |
|
It is not recommended to use raw types of generic classes, use the generic way: 1
| ArrayList<SomeType>[] myList = new ArrayList<SomeType>[10]; |
|
|
|
|
UprightPath
|
 |
«
Reply #6 - Posted
2012-03-17 20:10:38 » |
|
Does not work, ra4king!
Does not work.
You cannot instantiate any form of generic array. Any. When you attempt to do that, you'll get an error.
xD Sorry, this is an issue that I've had fun dealing with for a long time. Java will not allow you to use any form of Generic realization in an array structure.
|
|
|
|
Waterwolf
|
 |
«
Reply #7 - Posted
2012-03-17 20:17:24 » |
|
It does work.
Initializing generic array however doesnt (T[]) which is probably what you meant.
|
|
|
|
UprightPath
|
 |
«
Reply #8 - Posted
2012-03-17 20:22:54 » |
|
To follow up on that comment, to allow for a "Generic Array" you have to put a bit more work into it. Something like... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class GenericArray<Element> {
private Object[] elements; private final int size; public GenericArray(int size) { this.size = size; elements = new Object[size]; } public void setElementAt(int index, Element element) { elements[index] = element; } public Element getElementAt(int index) { return (Element) elements[index]; } } |
I've been delving around for a while, and this is perhaps the best way to do it because of the way that Java works. However, you have to maintain strict control over the elements array, to ensure that you'll only ever have objects of type Element in it. It does work.
Initializing generic array however doesnt (T[]) which is probably what you meant.
After correcting what ra4king wrote (He forgot the [] on the declaration) drop it into an IDE. It will not allow you compile it, giving you the "Generic Array Creation" error. Both in Netbeans and in Eclipse. Believe me I've tried to make this work.
|
|
|
|
UprightPath
|
 |
«
Reply #9 - Posted
2012-03-17 20:49:58 » |
|
Er, let me rephrase that bit. 1 2
| ArrayList<SomeObject>[] arrayOfArrayList; arrayOfArrayList = new ArrayList<SomeObject>[size]; |
You cannot create a generic array that way. If you can get an object of the generic type prior to creating the array, you can do this. 1 2
| T object = ... T[] elements = (T[]) Array.newInstance(object.getClass(), size); |
So, in this case, he can do this sort of mumbo-jumbo: 1 2 3 4 5 6 7
| ArrayList<Object> object = new ArrayList<Object>(); ArrayList<Object>[] myList; myList = (ArrayList<Object>[]) Array.newInstance(object.getClass(), 10); myList[0] = object; for(int i = 1; i < size; i++) { myList[i] = new ArrayList<Object>(); } |
Which is probably the best he can do. Because for the most part, Generics are not meant to work with arrays. It's a known fact that they don't play nicely together and probably never will. On a side note, is anyone else's code-block formatting off? Mine's got everything on the wrong line number. O.o Like shifted one down, with a leading blank.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
mlaux
|
 |
«
Reply #10 - Posted
2012-03-17 20:52:07 » |
|
I don't even remember seeing line numbers before; maybe they're a new feature and still not perfectly implemented?
|
|
|
|
UprightPath
|
 |
«
Reply #11 - Posted
2012-03-17 20:53:48 » |
|
Nah, they've been there for a while. They're just a very light grey.
|
|
|
|
ra4king
|
 |
«
Reply #12 - Posted
2012-03-17 20:55:39 » |
|
Does not work, ra4king!
Does not work.
You cannot instantiate any form of generic array. Any. When you attempt to do that, you'll get an error.
xD Sorry, this is an issue that I've had fun dealing with for a long time. Java will not allow you to use any form of Generic realization in an array structure.
 I've been expecting your reply. You cannot instantiate an array of generic type. However, you can instantiate an array of a known type regardless of whether it uses a generic type or not  1
| ArrayList<SomeType>[] myList = new ArrayList<SomeType>[10]; |
^^ this compiles, try it!
|
|
|
|
mlaux
|
 |
«
Reply #13 - Posted
2012-03-17 20:56:23 » |
|
Nah, they've been there for a while. They're just a very light grey.
Heh, maybe I just now started noticing them because they're off. Now that I've sufficiently derailed the thread, you may continue discussing arrays of ArrayLists... /walks off in shame
|
|
|
|
UprightPath
|
 |
«
Reply #14 - Posted
2012-03-17 21:00:27 » |
|
Nope! Still doesn't work. I've got this sitting in my IDE and it's giving me the generic array error. :3 1
| ArrayList<Object>[] myList = new ArrayList<Object>[10]; |
ArrayList is not generic. ArrayList<AnythingHere> is considered generic for the purpose of array instantiation. AnythingHere is generic, and is treated as such for object and array instantiation.
|
|
|
|
_Al3x
|
 |
«
Reply #15 - Posted
2012-03-17 21:07:16 » |
|
I did this and works just fine  1
| public ArrayList[] layers = new ArrayList[size]; |
Now, the hole point of this was to do some sort of "layers" to draw my things in some order: layers layer 0 = backgrounds layer 1 = enemies layer 2 = player layer 3 = shots, fxs, power ups. layer 4 = gui I feel that it ain't the best way to do it, but I'm working on while learning! This way I can, for example, keep things organized and keep everything "above" backgrounds and "below" the gui. Is this ok? BTW, I use brute force collision check to see if a shot collides with an alien for example. I used to check only one arraylist, but now I have to check 3: layer 1 with layer 2 and 3, layer 2 with layer 1 and 3 and layer 3 with layer 1 and 2. Any tips to make this simpler? 
|
|
|
|
sproingie
|
 |
«
Reply #16 - Posted
2012-03-17 21:28:35 » |
|
I did this and works just fine 1
| public ArrayList[] layers = new ArrayList[size]; |
Wrong on many levels. Honestly, what is the compulsion to use arrays here? Just use a pair of nested Lists and you don't have to juggle around what the rules are. Just STOP MIXING ARRAYS AND GENERICS and everything works out great.
|
|
|
|
UprightPath
|
 |
«
Reply #17 - Posted
2012-03-17 21:41:26 » |
|
Best way? Perhaps not. The way that works and that you understand it? Sometimes better than the best way. However, what you've got seems "right" for a given value of right. The way you describe it, it sounds like: A) Enemies cannot collide with each other. B) Power ups, FX/Shots can collide with enemies. The only way you could only have to check a single list would be to attempt to consolidate all of that data into a single list some how. Then manage several lists to ensure that removed objects are removed from all. It's probably too much work! However, that's for the collision system. You should be dividing up your logic from your GUI in the first place. Your GUI might read the from the logic portion of your program, but your program should have no knowledge of your GUI (Except through input methods of some sort). Either way, this is a completely different discussion than the ArrayList issue. :3 Honestly, what is the compulsion to use arrays here? Just use a pair of nested lists and you don't have to juggle around what the rules are. Just STOP MIXING ARRAYS AND GENERICS and everything works out great.
Because ArrayLists don't have a sense of bounding/strict indexing. If you're not doing lazy initialization, then there's no problem. 1 2 3 4 5 6 7 8 9 10 11 12 13
| Object[] array = new Object[10]; ArrayList list = new ArrayList(); Object holderObject; for(int i = 0; i < 10; i++) { holderObject = new Object(); array[0] = holderObject; list.add(holderObject); } array[0] == list.get(0); ... array[4] == list.get(4); ... array[9] == list.get(9); |
If you're doing lazy initialization, then you have to add code to ensure that you insert 'blanks' to the right depth in the ArrayList whenever you insert anything. 1 2 3 4 5 6 7 8 9 10 11 12 13
| Object[] array = new Object[10]; ArrayList list = new ArrayList(); Object holderObject = new Object(); array[4] = holderObject; if(list.size() < 4) { for(int i = list.size() -1; i < 4; i++) { list.add(null); } list.add(holderObject); } else { list.remove(4); list.add(4, holderObject); } |
Really, it's an issue of arrays being more convenient than a List in bounded/indexed circumstances. If you're going to attempt to use an ArrayList and bound it/give it strict indexing, you're going to have to write code that simulates an array anyway.
|
|
|
|
_Al3x
|
 |
«
Reply #18 - Posted
2012-03-17 22:06:18 » |
|
Well, trying to make my code better, I ended up messing everything  I originally had only one ArrayList where I put EVERY entity I had: - Enemies - Fx's - Player - GUI (not really a GUI yet, just a border and a place to display info, take a look at my showcase here- Shots - PowerUps - Background I realized that the order of drawing the entities made some of them be above the others, so I got the idea of sorting the entities so my background really is at the background. After a little while, I had my initEntities ordered so the first entity was my background and then the other entities. I didn't like to have to worry about the order of entities to be drawn like this, so I figured I would implement layers of entities. That way I could do something like Parallax (I think). It worked pretty well on my head, but implementing it is horrible! lol! So, that's what ArrayList[] layers is for. To keep an array of layers where 0 is the farthest and 4 is the nearest (the gui).  What do you think I should do? The collision method is a mess right now 
|
|
|
|
UprightPath
|
 |
«
Reply #19 - Posted
2012-03-17 22:18:16 » |
|
MVC! And no, not Marvel versus Capcom.
Ahem, really, you have to separate your concerns as best you can.
Your logical backend should be decoupled from your user interface front end. What this means is that it to your logic system should not have any idea of how it's receiving input. You should be able to write various different UIs for your game and it shouldn't require you to rewrite your game to do so.
You do this by refactoring/reengineering your system such that you remove all instances of UI specific data: Images, screen position, input recognizing code (Like hard coding it to recognize a right-keystroke to mean right), etc. You do, however, leave it to ability to provide data about global positioning, some sort of ID to help differentiate it between other objects, etc and methods to manipulate it. Such as 'makeCharacterWalk(Direction)' or something like that. (Think of this as the object that gets 'updated' on every tick.)
Then you write your GUI as a separate system. This system will know about your logic system, what data it can read from the system and what data it can provide to the system. This should where you take input/process it into commands. This system is the one that will handle the 'layering' required for animating your program. It knows about the background images, the object images, the gui, etc. It knows how what order to draw things, and asks the logic system for information about what in it to draw things. (Think of this as the object that gets 'rendered' on every tick.)
Really, this is a rather basic description of it, and probably wrong in points. However, you can look up the MVC Pattern/Architecture for more information.
|
|
|
|
Roquen
|
 |
«
Reply #20 - Posted
2012-03-18 07:09:03 » |
|
Type erasure makes java generics really sucky. The following is legal, but issues a warning if not suppressed.
@SuppressWarnings("unchecked") ArrayList<T>[] ai = new ArrayList[somenumber];
What's happening is that you have a setting that's treating a warning as an error.
|
|
|
|
UprightPath
|
 |
«
Reply #21 - Posted
2012-03-18 07:40:45 » |
|
No, that's different. That, my friend, is technically a form of type casting (To a point). You're not making an ArrayList<T>[], you're making an ArrayList[], and then making the program treat it as if it's an ArrayList<T>. Of course, for all intents and purposes that's alright. But it's technically not safe. The classic example is something like... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ArrayList[] basicList = new ArrayList[10]; ArrayList<Number>[] numberList = basicList; ArrayList<String>[] stringList = basicList; numberList[0] = new ArrayList<Number>(); numberList[0].add(10); stringList[1] = new ArrayList<String>(); stringList[1].add("Hello!"); try { System.out.println(stringList[0].get(0).length()); } catch (ClassCastException cce) { cce.printStackTrace(); } try { System.out.println(numberList[1].get(0).intValue()); } catch (ClassCastException cce) { cce.printStackTrace(); } |
Which results in: 1 2 3 4
| java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at sorting.Node.main(Node.java:40) java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number at sorting.Node.main(Node.java:45) |
|
|
|
|
Roquen
|
 |
«
Reply #22 - Posted
2012-03-18 09:48:39 » |
|
Look at the source code of ArrayList.
|
|
|
|
UprightPath
|
 |
«
Reply #23 - Posted
2012-03-18 09:53:06 » |
|
Yep.
I know. It only works because the ObjectType[] is never made available. If you ensure that you can't do what I put just below, then your fine.
It works, yes. But it's not guaranteed to be safe.
|
|
|
|
Roquen
|
 |
«
Reply #24 - Posted
2012-03-18 11:01:02 » |
|
Problem cases are identical.
|
|
|
|
aazimon
|
 |
«
Reply #25 - Posted
2012-03-18 14:06:16 » |
|
This way works. It's a simpler form from above. 1 2 3 4 5
| ArrayList<String>[] str = new ArrayList[9]; for (int i = 0; i < str.length; i++) { ArrayList<String> arrayList = new ArrayList<String>();
} |
|
|
|
|
Cero
|
 |
«
Reply #26 - Posted
2012-03-18 14:09:36 » |
|
Just use a pair of nested Lists and you don't have to juggle around what the rules are. Just STOP MIXING ARRAYS AND GENERICS and everything works out great.
This. Either all generics or all arrays. 1 2 3 4 5
| ArrayList<ArrayList<Object>> bigList = new ArrayList<ArrayList<Object>>(); for (ArrayList<Object> currentInnerList : bigList) { currentInnerList = new ArrayList<Object>(); } |
I just use arrays though.
|
|
|
|
_Al3x
|
 |
«
Reply #27 - Posted
2012-03-18 14:18:50 » |
|
Hey! Awesome input, many thanks to all!  I would like to put a hold on this thread, unless you'd like to keep discussing best programming techniques. As for me, I'm redesigning the whole project. Thank you all once again, I've bookmarked this already for future reference!  PS: You guys rock! 
|
|
|
|
ra4king
|
 |
«
Reply #28 - Posted
2012-03-18 14:34:14 » |
|
1 2 3 4 5
| ArrayList<ArrayList<Object>> bigList = new ArrayList<ArrayList<Object>>(); for (ArrayList<Object> currentInnerList : bigList) { currentInnerList = new ArrayList<Object>(); } |
That doesn't work, you are only assigning the local variable "currentInnerList" the ArrayList object  @UprightPath As I told you on IRC too, I just realized that the code I posted works in C#, which is where I used it and thought it was in Java. My bad on that part 
|
|
|
|
Cero
|
 |
«
Reply #29 - Posted
2012-03-18 15:16:16 » |
|
1 2 3 4 5
| ArrayList<ArrayList<Object>> bigList = new ArrayList<ArrayList<Object>>(); for (ArrayList<Object> currentInnerList : bigList) { currentInnerList = new ArrayList<Object>(); } |
That doesn't work, you are only assigning the local variable "currentInnerList" the ArrayList object  ah yes. I don't use for each that often - well just use a normal for loop then edit: actually I am thinking too much of arrays which I use normally. Of course you dont even have to iterate through here at initialization, because its still empty; being an empty list and an array which has a bunch of null pointers, is of course not the same...
|
|
|
|
|