AS3: Collection & Iterator
View Collection Documentation
View Iterator Documentation
Download Class & Example Files
Anyone who has worked with me in the past probably knows my distaste for Cairngorm and how I think it overcomplicates things. One really nice feature of it, however, is value objects (now known as data transfer objects, I believe) and collections. Value objects allow you to store data in a strongly typed class for later retrieval and a collection is just basically a fancier word for a strongly typed array that holds those value objects.
I use VOs to this day on pretty much any AS2 project that I pull external data into to store those objects much like I used to when I was a beginner and stored dynamic properties on an Object. This is a much more elegant way of controlling those objects and with a collection I can do things like get an object out by an ID or set up an extension of the Collection class and get objects out by whatever I want.
The Iterator class is just a port of the AS2 Iterator by Adobe as I couldn't find an AS3 version anywhere. Here that is:
-
/**
-
* @author Adobe [http://www.adobe.com]
-
* @author Ported to AS3 by Matt Przybylski [http://www.reintroducing.com]
-
* @version 1.0
-
*/
-
-
package com.reintroducing.utils
-
{
-
public class Iterator
-
{
-
//- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
-
-
private var _collection:Collection;
-
private var _cursor:int;
-
-
//- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
-
-
-
-
//- CONSTRUCTOR -------------------------------------------------------------------------------------------
-
-
/**
-
* Initialize the Iterator and maintain a link to it's Collection.
-
*
-
* @param $coll Collection to which this Iterator belongs.
-
*/
-
public function Iterator($coll:Collection):void
-
{
-
this._collection = $coll;
-
this._cursor = 0;
-
}
-
-
//- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
-
-
-
-
//- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
-
-
/**
-
* Returns true if the iteration has more items.
-
*
-
* @return Boolean true if iteration has more items.
-
*/
-
public function hasNext():Boolean
-
{
-
return (this._cursor <this._collection.getLength());
-
}
-
-
/**
-
* Return the next item in the iteration and increment the cursor. Returns null if the
-
* iteration has no more items.
-
*
-
* @return Object the next item in the Iteration.
-
*/
-
public function next():Object
-
{
-
return (this._collection.getItemAt(this._cursor++));
-
}
-
-
//- EVENT HANDLERS ----------------------------------------------------------------------------------------
-
-
-
-
//- GETTERS & SETTERS -------------------------------------------------------------------------------------
-
-
-
-
//- HELPERS -----------------------------------------------------------------------------------------------
-
-
public function toString():String
-
{
-
return "com.reintroducing.utils.Iterator";
-
}
-
-
//- END CLASS ---------------------------------------------------------------------------------------------
-
}
-
}
The Collection is also a port of the AS2 CollectionImpl.as class, although, like the Iterator, I took out the interface that goes with it and just made it one class.
-
/**
-
* @author Adobe [http://www.adobe.com]
-
* @author Ported to AS3 by Matt Przybylski [http://www.reintroducing.com]
-
* @version 1.0
-
*/
-
-
package com.reintroducing.utils
-
{
-
public class Collection extends Object
-
{
-
//- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
-
-
private var _items:Array;
-
-
//- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
-
-
-
-
//- CONSTRUCTOR -------------------------------------------------------------------------------------------
-
-
/**
-
* Helper class used to manage a collection of objects. This class is similar to the Java
-
* Collection interface. Developers can extend this class to create new Collection types
-
* that provide additional functionality such as ordering and sorting.
-
*
-
* @return Nothing
-
*/
-
public function Collection():void
-
{
-
super();
-
-
this._items = new Array();
-
}
-
-
//- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
-
-
// Finds an item within the Collection and returns it's index.
-
private function internalGetItem($item:Object):int
-
{
-
var result:int = -1;
-
-
for (var i:int = 0; i <this._items.length; i++)
-
{
-
if (this._items[i] == $item)
-
{
-
result = i;
-
break;
-
}
-
}
-
-
return result;
-
}
-
-
//- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
-
-
/**
-
* Adds a new item to the end of the Collection.
-
*
-
* @param $item * to be added to the Collection. If item is Null it will not be added to the Collection.
-
*
-
* @return Boolean true if the Collection was changed as a result of the operation.
-
*/
-
public function addItem($item:*):Boolean
-
{
-
var result:Boolean = false;
-
-
if ($item != null)
-
{
-
this._items.push($item);
-
-
result = true;
-
}
-
-
return result;
-
}
-
-
/**
-
* Removes a single item from the Collection. Returns false if item is not found.
-
*
-
* @param $item reference to Collection item to be removed from Collection.
-
*
-
* @return Boolean true if item is found and successfully removed. False if item is not found.
-
*/
-
public function removeItem($item:*):Boolean
-
{
-
var result:Boolean = false;
-
var itemIndex:int = this.internalGetItem($item);
-
-
if (itemIndex> -1)
-
{
-
this._items.splice(itemIndex, 1);
-
-
result = true;
-
}
-
-
return result;
-
}
-
-
/**
-
* Removes all items from the Collection.
-
*
-
* @return Nothing
-
*/
-
public function clear():void
-
{
-
this._items = new Array();
-
}
-
-
/**
-
* Returns true if this Collection contains the specified item.
-
*
-
* @param $item * whose presence in this collection is to be tested.
-
*
-
* @return Boolean true if this collection contains the specified item.
-
*/
-
public function contains($item:*):Boolean
-
{
-
return (this.internalGetItem($item)> -1);
-
}
-
-
/**
-
* Returns an item within the Collection using it's index.
-
*
-
* @param $index location of item within the Collection.
-
*
-
* @return * reference to item.
-
*/
-
public function getItemAt($index:int):*
-
{
-
return this._items[$index];
-
}
-
-
/**
-
* Returns an iterator over the elements in this collection. There are no guarantees concerning
-
* the order in which the elements are returned (unless this collection is an instance of some
-
* class that provides a guarantee).
-
*
-
* @return Iterator object that is used to iterate through the collection.
-
*/
-
public function getIterator():Iterator
-
{
-
return (new Iterator(this));
-
}
-
-
/**
-
* Returns the current length
-
*
-
* @return int value reflecting the number of items in this Collection.
-
*/
-
public function getLength():int
-
{
-
return this._items.length;
-
}
-
-
/**
-
* Returns true if the Collection is empty.
-
*
-
* @return Boolean true if Collection is empty.
-
*/
-
public function isEmpty():Boolean
-
{
-
return (this._items.length == 0);
-
}
-
-
//- EVENT HANDLERS ----------------------------------------------------------------------------------------
-
-
-
-
//- GETTERS & SETTERS -------------------------------------------------------------------------------------
-
-
-
-
//- HELPERS -----------------------------------------------------------------------------------------------
-
-
public function toString():String
-
{
-
return "com.reintroducing.utils.Collection";
-
}
-
-
//- END CLASS ---------------------------------------------------------------------------------------------
-
}
-
}
Now, I can't claim to have done a ton of stress tests on these classes, but it works for the basic usage that I've used it for so far. Here is an example of a VO and Collection I set up for a fake project (which you can preview in the example files). This is the XML file we used:
-
<?xml version="1.0" encoding="UTF-8"?>
-
-
<info>
-
<entry name="Portfolio" id="0" src="http://www.reintroducing.com" />
-
<entry name="Flash Dev Blog" id="1" src="http://evolve.reintroducing.com" />
-
<entry name="Company" id="2" src="http://www.b-r-e-e-d.com" />
-
<entry name="Girlfriend" id="3" src="http://www.jessicanovales.com" />
-
<entry name="Sport" id="4" src="http://www.nba.com" />
-
</info>
It's just some awesome information about myself all wrapped up into one neat little XML file.
Main.as
-
/**
-
* @author Matt Przybylski [http://www.reintroducing.com]
-
* @version 1.0
-
*/
-
-
package com.reintroducing
-
{
-
import flash.display.Sprite;
-
import flash.events.Event;
-
import flash.net.URLLoader;
-
import flash.net.URLRequest;
-
-
import com.reintroducing.debug.Environment;
-
import com.reintroducing.vo.TestVO;
-
import com.reintroducing.vo.TestVOCollection;
-
-
public class Main extends Sprite
-
{
-
//- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
-
-
private var _env:Environment;
-
private var _testVOCollection:TestVOCollection;
-
-
//- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
-
-
-
-
//- CONSTRUCTOR -------------------------------------------------------------------------------------------
-
-
public function Main():void
-
{
-
this._env = Environment.getInstance();
-
this._env.setPaths("../", "");
-
-
this.loadXML();
-
}
-
-
//- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
-
-
private function loadXML():void
-
{
-
var xmlURL:String = this._env.basePath + "xml/info.xml";
-
var xmlLoader:URLLoader = new URLLoader();
-
-
xmlLoader.addEventListener(Event.COMPLETE, parseXML);
-
xmlLoader.load(new URLRequest(xmlURL));
-
}
-
-
/**
-
*
-
*/
-
private function parseXML($evt:Event):void
-
{
-
var info:XML = new XML($evt.target.data);
-
var numItems:int = info.children().length();
-
var testVO:TestVO;
-
-
this._testVOCollection = new TestVOCollection();
-
-
for (var i:int = 0; i <numItems; i++)
-
{
-
testVO = new TestVO();
-
testVO.name = info.entry[i].@name;
-
testVO.id = int(info.entry[i].@id);
-
testVO.src = info.entry[i].@src;
-
-
this._testVOCollection.addItem(testVO);
-
}
-
-
this.traceBlogInfo();
-
}
-
-
/**
-
*
-
*/
-
private function traceBlogInfo():void
-
{
-
trace("Entry Name: " + this._testVOCollection.getItemAt(1).name);
-
trace("Entry ID: " + this._testVOCollection.getItemByID(1).id);
-
trace("Entry Source: " + this._testVOCollection.getItemByName("Flash Dev Blog").src);
-
}
-
-
//- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
-
-
-
-
//- EVENT HANDLERS ----------------------------------------------------------------------------------------
-
-
-
-
//- GETTERS & SETTERS -------------------------------------------------------------------------------------
-
-
-
-
//- HELPERS -----------------------------------------------------------------------------------------------
-
-
public override function toString():String
-
{
-
return "com.reintroducing.Main";
-
}
-
-
//- END CLASS ---------------------------------------------------------------------------------------------
-
}
-
}
TestVO.as
-
/**
-
* @author Matt Przybylski [http://www.reintroducing.com]
-
* @version 1.0
-
*/
-
-
package com.reintroducing.vo
-
{
-
public class TestVO
-
{
-
//- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
-
-
-
-
//- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
-
-
public var name:String;
-
public var id:int;
-
public var src:String;
-
-
//- CONSTRUCTOR -------------------------------------------------------------------------------------------
-
-
public function TestVO():void
-
{
-
-
}
-
-
//- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
-
-
-
-
//- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
-
-
-
-
//- EVENT HANDLERS ----------------------------------------------------------------------------------------
-
-
-
-
//- GETTERS & SETTERS -------------------------------------------------------------------------------------
-
-
-
-
//- HELPERS -----------------------------------------------------------------------------------------------
-
-
public function toString():String
-
{
-
return "com.reintroducing.vo.TestVO";
-
}
-
-
//- END CLASS ---------------------------------------------------------------------------------------------
-
}
-
}
TestVOCollection.as
-
/**
-
* @author Matt Przybylski [http://www.reintroducing.com]
-
* @version 1.0
-
*/
-
-
package com.reintroducing.vo
-
{
-
import com.reintroducing.utils.Collection;
-
import com.reintroducing.utils.Iterator;
-
-
public class TestVOCollection extends Collection
-
{
-
//- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
-
-
-
-
//- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
-
-
-
-
//- CONSTRUCTOR -------------------------------------------------------------------------------------------
-
-
public function TestVOCollection():void
-
{
-
super();
-
}
-
-
//- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
-
-
-
-
//- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
-
-
/**
-
*
-
*/
-
public function getItemByID($id:int):TestVO
-
{
-
var itr:Iterator = this.getIterator();
-
var testVO:TestVO;
-
var rVO:TestVO;
-
-
while (itr.hasNext())
-
{
-
testVO = TestVO(itr.next());
-
-
if (testVO.id == $id)
-
{
-
rVO = testVO;
-
break;
-
}
-
}
-
-
return rVO;
-
}
-
-
/**
-
*
-
*/
-
public function getItemByName($name:String):TestVO
-
{
-
var itr:Iterator = this.getIterator();
-
var testVO:TestVO;
-
var rVO:TestVO;
-
-
while (itr.hasNext())
-
{
-
testVO = TestVO(itr.next());
-
-
if (testVO.name == $name)
-
{
-
rVO = testVO;
-
break;
-
}
-
}
-
-
return rVO;
-
}
-
-
//- EVENT HANDLERS ----------------------------------------------------------------------------------------
-
-
-
-
//- GETTERS & SETTERS -------------------------------------------------------------------------------------
-
-
-
-
//- HELPERS -----------------------------------------------------------------------------------------------
-
-
public override function toString():String
-
{
-
return "com.reintroducing.vo.TestVOCollection";
-
}
-
-
//- END CLASS ---------------------------------------------------------------------------------------------
-
}
-
}
As you can see, the TestVO.as class just basically holds the information from my XML file. It basically represents one node out of the XML, an object that will contain a name, id, and src. You can make your VO have as many properties as you'd like or need.
In the TestVOCollection.as class you will notice that I extended Collection and added methods to get an item by ID or by Name. You can add as many methods here as you'd like to be able to retrieve items by whatever value you want. The method will almost always look the same except pull the data by the property you specify in it and return your appropriate value object.
Are these classes super necessary? Probably not, but it keeps my projects nice and tidy.
If you found this post useful, please consider leaving a comment, subscribing to the feed, or making a small donation.













Very nice Matt! I did something similar to what you have but of course mine is setup differently.
Why do you extend Object don't all classes naturally extend Object? I would think that extending Object would kinda be redundant, but what do I know I am just a guacamalan!