Leverage ColdFusion Array's Underlying Iterator Object
Posted September 9, 2006 at 8:18 AM by Ben Nadel
Just a quick little experiment here to test and demo how you can use the Java iterator object that is accessible from the ColdFusion array object. An array is a collection, and like a lot of collections in Java, it has a method to return an iterator that will iterate over all the items in the collection using the iterator interface.
The one thing that is nice about the iterator is that it uses a very standard, very simple looping syntax. Check it out below:
- <!--- Create new data array. --->
- <cfset arrGirls = ArrayNew( 1 ) />
- <!--- Resize array to accomodate data. --->
- <cfset ArrayResize( arrGirls, 4 ) />
- <!--- Add data. --->
- <cfset arrGirls[ 1 ] = StructNew() />
- <cfset arrGirls[ 1 ].Name = "Libby" />
- <cfset arrGirls[ 1 ].Freckles = true />
- <cfset arrGirls[ 1 ].Cute = "Very" />
- <cfset arrGirls[ 2 ] = StructNew() />
- <cfset arrGirls[ 2 ].Name = "Marci" />
- <cfset arrGirls[ 2 ].Freckles = false />
- <cfset arrGirls[ 2 ].Cute = "Not so much" />
- <cfset arrGirls[ 3 ] = StructNew() />
- <cfset arrGirls[ 3 ].Name = "Julia" />
- <cfset arrGirls[ 3 ].Freckles = false />
- <cfset arrGirls[ 3 ].Cute = "Yes" />
- <cfset arrGirls[ 4 ] = StructNew() />
- <cfset arrGirls[ 4 ].Name = "Liz" />
- <cfset arrGirls[ 4 ].Freckles = false />
- <cfset arrGirls[ 4 ].Cute = "Yes" />
- <!--- Get array iterator. --->
- <cfset objIterator = arrGirls.Iterator() />
- Iterator over array. This is a conditional loop that will
- keep looping until the end of the array is reached.
- <cfloop condition="objIterator.HasNext()">
- <!--- Get next item in the array (from the iterator). --->
- <cfset objGirl = objIterator.Next() />
- Has Freckles: #YesNoFormat( objGirl.Freckles )#<br />
- Is Cute: #objGirl.Cute#
To me, this just looks very simple and nice. That is NOT to say that this is better than the traditional index loop from 1 to the ArrayLen() of the array. It's just different.
What Other People Are Searching For
Yeah, but the catch is that the iterator is easily invalidated. Some quick testing revealed that no matter what you do to the array, any modification to the structure resulted in an invalid iterator and a thrown exception on the next use of the iterator.
I tried deleting elements before and after the iterator with ArrayDeleteAt, as well as inserting elements before and after the iterator with ArrayAppend, etc. All made a big kaboom.
However, the iterator's remove() method still works. I guess that would be useful for stack-type arrays or maybe even a filtering function. The loss of the element index makes the array itself essentially read-or-destroy-only if using an iterator.
You are saying you used ArrayDeleteAt() WHILE you were in the iterator? I have not tested that. However, if I manipulate the array before getting the iterator, or after I am done with all iterator features, everything works fine.
If you look at the Java methods for the Iterator, you will see that there is no way to reset the iterator. No MoveToFirst() or anything like that. The iterator creates a one-way reader. You can't use the iterator more than once. If you get an iterator, it doesn't even matter if you manipulate the array - if you want to use the iterator again, you have to re-get it so that it can start from the end.