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:

Actionscript:
  1. /**
  2. * @author Adobe [http://www.adobe.com]
  3. * @author Ported to AS3 by Matt Przybylski [http://www.reintroducing.com]
  4. * @version 1.0
  5. */
  6.  
  7. package com.reintroducing.utils
  8. {
  9.     public class Iterator
  10.     {
  11. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  12.  
  13.         private var _collection:Collection;
  14.         private var _cursor:int;
  15.        
  16. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  17.        
  18.        
  19.        
  20. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  21.    
  22.         /**
  23.          * Initialize the Iterator and maintain a link to it's Collection.
  24.          *
  25.          * @param $coll Collection to which this Iterator belongs.
  26.          */
  27.         public function Iterator($coll:Collection):void
  28.         {
  29.             this._collection = $coll;
  30.             this._cursor = 0;
  31.         }
  32.  
  33. //- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
  34.        
  35.        
  36.        
  37. //- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
  38.    
  39.         /**
  40.          * Returns true if the iteration has more items.
  41.          *
  42.          * @return Boolean true if iteration has more items.
  43.          */
  44.         public function hasNext():Boolean
  45.         {
  46.             return (this._cursor <this._collection.getLength());
  47.         }
  48.        
  49.         /**
  50.          * Return the next item in the iteration and increment the cursor. Returns null if the
  51.          * iteration has no more items.
  52.          *
  53.          * @return Object the next item in the Iteration.
  54.          */
  55.         public function next():Object
  56.         {
  57.             return (this._collection.getItemAt(this._cursor++));
  58.         }   
  59.    
  60. //- EVENT HANDLERS ----------------------------------------------------------------------------------------
  61.    
  62.        
  63.    
  64. //- GETTERS & SETTERS -------------------------------------------------------------------------------------
  65.    
  66.        
  67.    
  68. //- HELPERS -----------------------------------------------------------------------------------------------
  69.    
  70.         public function toString():String
  71.         {
  72.             return "com.reintroducing.utils.Iterator";
  73.         }
  74.    
  75. //- END CLASS ---------------------------------------------------------------------------------------------
  76.     }
  77. }

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.

Actionscript:
  1. /**
  2. * @author Adobe [http://www.adobe.com]
  3. * @author Ported to AS3 by Matt Przybylski [http://www.reintroducing.com]
  4. * @version 1.0
  5. */
  6.  
  7. package com.reintroducing.utils
  8. {
  9.     public class Collection extends Object
  10.     {
  11. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  12.  
  13.         private var _items:Array;
  14.        
  15. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  16.        
  17.        
  18.        
  19. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  20.    
  21.         /**
  22.          * Helper class used to manage a collection of objects. This class is similar to the Java
  23.          * Collection interface.  Developers can extend this class to create new Collection types
  24.          * that provide additional functionality such as ordering and sorting.
  25.          *
  26.          * @return Nothing
  27.          */
  28.         public function Collection():void
  29.         {
  30.             super();
  31.            
  32.             this._items = new Array();
  33.         }
  34.        
  35. //- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
  36.        
  37.         // Finds an item within the Collection and returns it's index.
  38.         private function internalGetItem($item:Object):int
  39.         {
  40.             var result:int = -1;
  41.            
  42.             for (var i:int = 0; i <this._items.length; i++)
  43.             {
  44.                 if (this._items[i] == $item)
  45.                 {
  46.                     result = i;
  47.                     break;
  48.                 }
  49.             }
  50.            
  51.             return result;
  52.         }
  53.        
  54. //- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
  55.    
  56.         /**
  57.          * Adds a new item to the end of the Collection.
  58.          *
  59.          * @param $item * to be added to the Collection. If item is Null it will not be added to the Collection.
  60.          *
  61.          * @return Boolean true if the Collection was changed as a result of the operation.
  62.          */
  63.         public function addItem($item:*):Boolean
  64.         {
  65.             var result:Boolean = false;
  66.            
  67.             if ($item != null)
  68.             {
  69.                 this._items.push($item);
  70.                
  71.                 result = true;
  72.             }
  73.            
  74.             return result;
  75.         }
  76.        
  77.         /**
  78.          * Removes a single item from the Collection.  Returns false if item is not found.
  79.          *
  80.          * @param $item reference to Collection item to be removed from Collection.
  81.          *
  82.          * @return Boolean true if item is found and successfully removed.  False if item is not found.
  83.          */
  84.         public function removeItem($item:*):Boolean
  85.         {
  86.             var result:Boolean = false;
  87.             var itemIndex:int = this.internalGetItem($item);
  88.            
  89.             if (itemIndex> -1)
  90.             {
  91.                 this._items.splice(itemIndex, 1);
  92.                
  93.                 result = true;
  94.             }
  95.            
  96.             return result;
  97.         }
  98.        
  99.         /**
  100.          * Removes all items from the Collection.
  101.          *
  102.          * @return Nothing
  103.          */
  104.         public function clear():void
  105.         {
  106.             this._items = new Array();
  107.         }
  108.        
  109.         /**
  110.          * Returns true if this Collection contains the specified item.
  111.          *
  112.          * @param $item * whose presence in this collection is to be tested.
  113.          *
  114.          * @return Boolean true if this collection contains the specified item.
  115.          */
  116.         public function contains($item:*):Boolean
  117.         {
  118.             return (this.internalGetItem($item)> -1);
  119.         }
  120.        
  121.         /**
  122.          * Returns an item within the Collection using it's index.
  123.          *
  124.          * @param $index location of item within the Collection.
  125.          *
  126.          * @return * reference to item.
  127.          */
  128.         public function getItemAt($index:int):*
  129.         {
  130.             return this._items[$index];
  131.         }
  132.        
  133.         /**
  134.          * Returns an iterator over the elements in this collection. There are no guarantees concerning
  135.          * the order in which the elements are returned (unless this collection is an instance of some
  136.          * class that provides a guarantee).
  137.          *
  138.          * @return Iterator object that is used to iterate through the collection.
  139.          */
  140.         public function getIterator():Iterator
  141.         {
  142.             return (new Iterator(this));
  143.         }
  144.        
  145.         /**
  146.          * Returns the current length
  147.          *
  148.          * @return int value reflecting the number of items in this Collection.
  149.          */
  150.         public function getLength():int
  151.         {
  152.             return this._items.length;
  153.         }
  154.        
  155.         /**
  156.          * Returns true if the Collection is empty.
  157.          *
  158.          * @return Boolean true if Collection is empty.
  159.          */
  160.         public function isEmpty():Boolean
  161.         {
  162.             return (this._items.length == 0);
  163.         }
  164.    
  165. //- EVENT HANDLERS ----------------------------------------------------------------------------------------
  166.    
  167.        
  168.    
  169. //- GETTERS & SETTERS -------------------------------------------------------------------------------------
  170.    
  171.        
  172.    
  173. //- HELPERS -----------------------------------------------------------------------------------------------
  174.    
  175.         public function toString():String
  176.         {
  177.             return "com.reintroducing.utils.Collection";
  178.         }
  179.    
  180. //- END CLASS ---------------------------------------------------------------------------------------------
  181.     }
  182. }

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:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2.  
  3. <info>
  4.     <entry name="Portfolio" id="0" src="http://www.reintroducing.com" />
  5.     <entry name="Flash Dev Blog" id="1" src="http://evolve.reintroducing.com" />
  6.     <entry name="Company" id="2" src="http://www.b-r-e-e-d.com" />
  7.     <entry name="Girlfriend" id="3" src="http://www.jessicanovales.com" />
  8.     <entry name="Sport" id="4" src="http://www.nba.com" />
  9. </info>

It's just some awesome information about myself all wrapped up into one neat little XML file. :P

Main.as

Actionscript:
  1. /**
  2. * @author Matt Przybylski [http://www.reintroducing.com]
  3. * @version 1.0
  4. */
  5.  
  6. package com.reintroducing
  7. {
  8.     import flash.display.Sprite;
  9.     import flash.events.Event;
  10.     import flash.net.URLLoader;
  11.     import flash.net.URLRequest;
  12.    
  13.     import com.reintroducing.debug.Environment;
  14.     import com.reintroducing.vo.TestVO;
  15.     import com.reintroducing.vo.TestVOCollection;   
  16.  
  17.     public class Main extends Sprite
  18.     {
  19. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  20.  
  21.         private var _env:Environment;
  22.         private var _testVOCollection:TestVOCollection;
  23.        
  24. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  25.        
  26.        
  27.        
  28. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  29.    
  30.         public function Main():void
  31.         {
  32.             this._env = Environment.getInstance();
  33.             this._env.setPaths("../", "");
  34.            
  35.             this.loadXML();
  36.         }
  37.        
  38. //- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
  39.        
  40.         private function loadXML():void
  41.         {
  42.             var xmlURL:String = this._env.basePath + "xml/info.xml";
  43.             var xmlLoader:URLLoader = new URLLoader();
  44.            
  45.             xmlLoader.addEventListener(Event.COMPLETE, parseXML);
  46.             xmlLoader.load(new URLRequest(xmlURL));
  47.         }
  48.        
  49.         /**
  50.          *
  51.          */
  52.         private function parseXML($evt:Event):void
  53.         {
  54.             var info:XML = new XML($evt.target.data);
  55.             var numItems:int = info.children().length();
  56.             var testVO:TestVO;
  57.            
  58.             this._testVOCollection = new TestVOCollection();
  59.            
  60.             for (var i:int = 0; i <numItems; i++)
  61.             {
  62.                 testVO   = new TestVO();
  63.                 testVO.name = info.entry[i].@name;
  64.                 testVO.id   = int(info.entry[i].@id);
  65.                 testVO.src  = info.entry[i].@src;
  66.                
  67.                 this._testVOCollection.addItem(testVO);
  68.             }
  69.            
  70.             this.traceBlogInfo();
  71.         }
  72.        
  73.         /**
  74.          *
  75.          */
  76.         private function traceBlogInfo():void
  77.         {
  78.             trace("Entry Name: " + this._testVOCollection.getItemAt(1).name);
  79.             trace("Entry ID: " + this._testVOCollection.getItemByID(1).id);
  80.             trace("Entry Source: " + this._testVOCollection.getItemByName("Flash Dev Blog").src);
  81.         }
  82.        
  83. //- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
  84.    
  85.        
  86.    
  87. //- EVENT HANDLERS ----------------------------------------------------------------------------------------
  88.    
  89.        
  90.    
  91. //- GETTERS & SETTERS -------------------------------------------------------------------------------------
  92.    
  93.        
  94.    
  95. //- HELPERS -----------------------------------------------------------------------------------------------
  96.    
  97.         public override function toString():String
  98.         {
  99.             return "com.reintroducing.Main";
  100.         }
  101.    
  102. //- END CLASS ---------------------------------------------------------------------------------------------
  103.     }
  104. }

TestVO.as

Actionscript:
  1. /**
  2. * @author Matt Przybylski [http://www.reintroducing.com]
  3. * @version 1.0
  4. */
  5.  
  6. package com.reintroducing.vo
  7. {
  8.     public class TestVO
  9.     {
  10. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  11.  
  12.        
  13.        
  14. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  15.        
  16.         public var name:String;
  17.         public var id:int;
  18.         public var src:String;
  19.        
  20. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  21.    
  22.         public function TestVO():void