Sign in to follow this  
edd1986

[java] A question about using ArrayList

Recommended Posts

Hi, currently i have several objects kept in a normal array. I need to loop through each element in this array and perform the same operation on it. I am trying to add in the ability for the user to add in new objects so i need to change the array to an array list. i understand how to add objects to a list and how to loop through n number of times using an iterator. What i don't really understand is how to perform an operation on the object at the iterators index. for example this is the code i am trying:
  Iterator it = theShapes.iterator();
  while (it.hasNext())
  {
      it.next().transform(worldMat);
  }

I have also tried:
(theObjects.get(0)).transform(worldMat);

These however flag an error about not being able to find the transform function (when i know it is there as i have been using it when i was working with a simple array) Any help? Thanks in advance

Share this post


Link to post
Share on other sites
In Java 1.4 all objects are stored in the ArrayList as instances of Object (which is the super class of all other classes in Java). This means that objects returned from the ArrayList must be casted to the appropriate class before use.

Iterator it = theShaped.iterator();
while (it.hasNext()) {
((MyClass)(it.next())).transform(worldMat);
}





If you are using Java 5.0 however this can be simplified by the use of Generics and the foreach construct:

ArrayList<MyClass> theShaped = new ArrayList<MyClass>
...add elements to the ArrayList...

for (MyClass element : theShaped) {
element.transform(worldMat);
}



Share this post


Link to post
Share on other sites
ah yes, thanks :)

just one more problem now.

I have the code:


((SceneElement)theObjects.get(it.next())).transform(worldMat)




However now i get an error saying 'cannot resolve symbol method get'

I also tried this:

((SceneElement)(it.next())).transform(deviceMat);


This compiles but produces the runtime error:

"No such element exception"

[Edited by - edd1986 on April 3, 2006 7:47:05 AM]

Share this post


Link to post
Share on other sites
Your second code is the correct one. But it will throw a NoSuchElementException if there are no more elements in the collection. You can use the .hasNext() method on the Iterator before each next() call. The first example in my previous post shows this.

Share this post


Link to post
Share on other sites
When iterating on a List implementation, use the ListIterator. Not only optimal, but also, elegant ;)

Also, if I seem to understand what you're trying to do, I think a LinkedList would be the most efficient Collection type to use.

Ah, code to iterate over a list:


List < GameObject > gObjs = new LinkedList < GameObject >();
ListIterator < GameObject > it = gObjs.listIterator();

while ( it.hasNext() ) {
it.next().doSomething();
}


Son Of Cain

Share this post


Link to post
Share on other sites
thanks for the help again. this is confusing as i think i am already checking .hasNext() correctly. This is the code that produces the NoSuchElement exception:

Code:

public void worldToDevice()
{
Iterator it = theObjects.iterator();
while (it.hasNext())
{
//perform relevant transformations
((SceneElement)(it.next())).transform(deviceMat);
}
}




Also, will this code perform the transform on the first object in the list? as i am calling transform for 'it.next'

[Edited by - edd1986 on April 3, 2006 8:14:20 AM]

Share this post


Link to post
Share on other sites
Yes, the first call to next() retrieves the first element on the list.

About the exception, are you sure that all of its elements are of the same class (SceneElement)?

Son Of Cain

Share this post


Link to post
Share on other sites
Well SceneElement is an abstract class, with 'House' and 'Tree' inheriting from it, could this be the problem?

Share this post


Link to post
Share on other sites
No, seems to be fine. Post more code, please =D

Also, I forgot to add on the previous post that you can use a for each approach with Java 1.5:


for (SceneElement e : gObjs) {
e.doSomething();
}


That will iterate through the List the same way as if you used an Iterator.

Son Of Cain

Share this post


Link to post
Share on other sites
I think that code should be all that is needed. The only ommitted code is a few matrix transformations. The error points to this function.

There were three objects in my list. the first two were 'House' objects and the third was a 'Tree'. I put a println in my function to see where it broke. It printed twice and crashed when trying to reach the third element, could be a co-incedence that the third object is a Tree whereas the others are Houses.

It's not essential i solve this anymore as i have just added an oversized normal array with a counter of how many elements are filled. Not perfect but at least it works.

Share this post


Link to post
Share on other sites
My guess is you are doing something like this:


public void worldToDevice() {
Iterator it = theObjects.iterator();
while (it.hasNext())
{
((SceneElement)(it.next())).myFirstMethod();
((SceneElement)(it.next())).mySecondMethod(); // could give error
}
}


Instead of:


public void worldToDevice() {
Iterator it = theObjects.iterator();
while (it.hasNext())
{
SceneElement e = (SceneElement)it.next();
e.myFirstMethod();
e.mySecondMethod();
}
}


Each call to Iterator.next() gives the next element of the iterator (if there is such element).

Share this post


Link to post
Share on other sites
How is theObjects declared and initialized?


List theObjects = new ArrayList();
// non-generic version
// -> not typesafe
// -> casting required


If it looks something like the above, try this:


List<SceneElement> theObjects = new ArrayList<SceneElement>();
// generic version
// -> typesafe
// -> no casting required


Because now you can do this much nicer, without the need for handlings iterators manually:


for (SceneElement e : theObjects)
{
e.transform(deviceMat);
}


Quote:
Original post by edd1986
i have just added an oversized normal array with a counter of how many elements are filled. Not perfect but at least it works.

Not perfect? It's horrible!

I guess Lotuspec is right, you call it.next() more than once per loop. If that's not the case post more code.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this