[java] Java arrays, Vectors, ArrayLists

Started by
4 comments, last by informis 22 years, 10 months ago
I just read the article on Java game programming and had some more detail on Vectors, arrays, and other classes you might want to consider using. Arrays work well, and Vectors are convenient, but when is really the best time to use each? First off, arrays are fast and work well when you know how big they will be up front. If you know you will always store exactly 100 elements, simply make an array for 100 elements. Be warned, though, that multiple threads accessing the same array could cause problems if the elements of the array are actually being modified. Vectors do two things better than arrays: Vectors can grow or shrink (which is good for memory efficieny) and they are synchronized, meaning the problem described above with arrays is avoided. This comes with a cost, though, which is that the Vector is much slower than the array. The ArrayList is a cool class that is totally underused by a lot of people. Let''s say you''re not sure how many elements to store, but you don''t care about synchronization. With the Vector and array you''re out of luck, but the ArrayList does this nicely. This gives you a fast, growable, non-synchronized array object. Finally, I''d highly recommend the use of the List interface in all methods definitions. That is, all your methods should take Lists as parameters or return Lists as return values. Since both the Vector and the ArrayList implement List, it makes it easy to change a method that returns a non-synchronized ArrayList to one that returns a synchronized Vector. The only thisng that would change would be your internal method implementation. The List interface itself has all the methods you could want for manipulating array type objects (i.e. add(), get(), iterator(), etc.) I hope this was helpful. Informis
Advertisement
What about all that casting? Doesn''t it slow down the program a little, while also making it harder to read? I don''t know if it bothers other people but I just don''t like it when a commonly used method returns an Object, particularly if you always know what it is going to return anyway. Right now I''m using arrays that are a little bigger than they need to be and maintaining a count on my own, so I sort of have a vector. I''m also using next references in some of my classes that tend to always be found in small linked lists. So far things seem to be working fine but I''d like something like that STL I''ve heard so much about.
> Vectors can grow or shrink
> (which is good for memory efficieny)
Umm, it''s actually just the opposite, because the only way the java.util.Vector changes its size is by creating a new array that has the needed new size and copying stuff from the old array to this new array. So if you keep changing the size a lot you actually end up filling your memory with discarded arrays. This will at some point cause GC to kick in and take over the CPU for a while.

Also you should notice that java.util.Vector actually grows automatically, but doesn''t automatically shrink its size.

> I''d highly recommend the use of the List
> interface in all methods definitions.
Bad idea, because List returns its contents as Object references and if you now put objects X in your SomeObject.getValues() method and return the List and the object that uses your SomeObject expects that the list contains objects Y you''ll get a runtime exception.

This is bad because the only way to you even can notice this bug is to test the part of your application that does this. If you use some other way e.g. return an array of objects X from the method, you''ll find the bug upon compiling the code.

Besides as is mentioned in Tuning Java Performance, casting between object types does steal some CPU time as the cast has to be checked by the runtime each time it is made.
-Pasi Keranen
>> Vectors can grow or shrink
>> (which is good for memory efficieny)
>
>Umm, it''s actually just the opposite, because the only way the
>java.util.Vector changes its size is by creating a new array
>that has the needed new size and copying stuff from the old
>array to this new array. So if you keep changing the size a lot
>you actually end up filling your memory with discarded arrays.
>This will at some point cause GC to kick in and take over the
>CPU for a while.

By "memory efficiency" I meant avoiding the need to allocate more
slots than you''ll need, like a previous poster suggested. And
reallocating your own arrays would be just as slow as having a
Vector do it (assuming the Vector is coded intelligently). If we''re
talking one of the Collections framework classes vs. arrays for
growable storage, I''ll take Vectors.

>Also you should notice that java.util.Vector actually grows
>automatically, but doesn''t automatically shrink its size.

Good call. I''ve been coding some object pooling stuff that does
this and I was getting ahead of myself!

>> I''d highly recommend the use of the List
>> interface in all methods definitions.
>Bad idea, because List returns its contents as Object
>references and if you now put objects X in your
>SomeObject.getValues() method and return the List and the
>object that uses your SomeObject expects that the list contains
>objects Y you''ll get a runtime exception.

This is no worse than what happens with Vectors, which return Object
references anyway. When you call Vector.get() you''re really calling
the Vector''s implementation of List.get(), so I don''t see much choice
if you want a generic collection class. You don''t need to cast a List
to anything to use it. For example, in a class called Foo:

public List getEmptyList() {return new Vector(5);}

Then:

Foo foo = new Foo();
List myList = foo.getEmptyList();

Then, I can change getEmptyList''s implementation to return an ArrayList:

public List getEmptyList() {return new ArrayList(5);}

...and my "Foo" code doesn''t have to change. Yes, there is the implicit
cast from Vector/ArrayList to List, but if you want design flexibility,
this is a small price to pay.

Ideally, we''d use specialized collection classes. If I know I only want
to store Widget objects, then I create my own WidgetVector whose return
values and parameters are all Widget objects. Then, I avoid the extra
cast, which is cool.

Informis
quote:Original post by informis
By "memory efficiency" I meant avoiding the need to allocate more slots than you''ll need, like a previous poster suggested.

Actually Vector does usually reserve more slots than are needed. Especially if you don''t specify the capacity increment it always doubles the size of the reserved array.

quote:Original post by informis
This is no worse than what happens with Vectors, which return Object references anyway.

I know, the whole Collections framework along with the old util classes for datastorage suffer from this same phenomena.

There was some talk a few years back about generics being implemented as part of the Java language, but it seems that didn''t happen. Generics can be thought of being equivalent to C++ code templates. You define a data storage class by leaving the stored type empty (you put some placeholder like /type/ in its place). Then when you instantiate the class in your code you define the type you want to use, the compiler notices the type and compiles a class that actually uses the type you defined. This is effecicient and above all the type safety check is done during the compiling.

I''ve seriously thought about emulating the C++ type templates by doing generic templates that have "/type/" written in the place of stored object type. Then when I need e.g. a class for storing ByteStrings I just search-replace the template converting "/type/" to "ByteString". After this I''ve got a type safe (and a bit faster) data storage for ByteStrings.

quote:Original post by informis
but if you want design flexibility, this is a small price to pay.

Until you end up debugging 20000 lines of code, just because someone in the development team thought the Vector contains Widget''s when it should only contain Doodad''s. Happened to me once at work, not too nice of an experience. These kind of errors can happen and when they happen it''s really hard to find out where exactly someone places a wrong object in the data structure.


quote: Ideally, we''d use specialized collection classes.

Finally we agree on something.

-
JavaNerd
-Pasi Keranen
This is probably off topic,
JavaNerd, did you know the folks over at sun are going to implement generics for the next (or future) releases of the JDK, here is a link:
http://www.javaworld.com/javaworld/javaone01/j1-01-improvements.html

cool, huh?.

Cheers, JP.


==============================================
I feel like a kid in some kind of store...
==============================================
www.thejpsystem.com
==============================================I feel like a kid in some kind of store... ============================================== www.thejpsystem.com

This topic is closed to new replies.

Advertisement