배열이라는 것은 비슷한 Data를 저장해 놓은 것인데, 저장하는 방법이 두 가지가 있습니다. 첫번째로 0부터 순서대로 번호를 매겨서 그 번호로 원소를 찾는 방법(인덱스 배열, indexed array)이 있고, 두번째로 번호 대신에 문자열이나 객체등으로 배열의 원소를 찾는 방법(연관 배열, associative array)이 있습니다.

 

 이 포스팅은 Actionscript에서 연관배열을 만드는 클래스인 Dictionary에 대해 간단히 알아보겠습니다.

 

1. 연관배열

 

Dictionary클래스를 알아보기전에 연관배열(Hash 혹은 Map이라 부름)이 무엇인지 알아보고, actionscript에서 연관배열을 어떻게 만드는지 알아보겠습니다.

 

위에서 언급했듯이 연관배열이란 Key에 Data를 짝을 지어주어 자료를 저장하고, 그 Key값으로 해당 Data를 찾는 것입니다.

 

연관 배열(associative array)은 자료구조의 하나로, 여러 개의 (키, 값)을 담으며 키를 통해 그에 연관되는 값을 접근할 수 있다. 연상 배열, 결합형 배열, (map), 사전(dictioanry)으로 부르기도 한다.

* 출처 : 위키피아

 

Actionscript에서 연관배열을 만드는 방법에는 두가지가 있습니다.  아래는 연관배열을 만드는 두가지 방법을 나타내주는 간단한 예제입니다.

 

 

<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

                     xmlns:s="library://ns.adobe.com/flex/spark"

                     xmlns:mx="library://ns.adobe.com/flex/mx"

                     creationComplete="init();">

      <fx:Script>

            <![CDATA[

                 

                  // 1-1. 객체 리터럴을 사용하여 선언과 동시에 초기화

                  private var capitalInfo:Object = {national : "KOREA", capital : "SEOUL"}; 

                  private var capitalInfo2:Object;

                  private var capitalInfo3:Array;

                 

                  private function init():void

                  {

                        // 1-2. Object클래스의 생성자를 이용하여 초기화

                        // 키값에 공백이 있으면 안됨

                        capitalInfo2 = new Object();

                        capitalInfo2["national"] = "KOREA";

                        capitalInfo2["capital"] = "SEOUL";

                       

                        // 2. Array유형으로 선언할 경우 객체 리터럴을 사용할 없다.

                        //    array속성 사용못함.별다른 이점 없음. 인덱스 배열만드는데 사용.

                        capitalInfo3 = new Array();

                        capitalInfo3["national"] = "KOREA";

                        capitalInfo3["capital"] = "SEOUL";

                  }

                 

                  private function show():void

                  {

                        window.text += capitalInfo["national"] + "-";

                        window.text += capitalInfo["capital"] + "\n";

                        window.text += capitalInfo2["national"] + "-";

                        window.text += capitalInfo2["capital"] + "\n";

                        window.text += capitalInfo3["national"] + "-";

                        window.text += capitalInfo3["capital"] + "\n";

                  }

            ]]>

      </fx:Script>

      <s:VGroup>

            <s:TextArea id="window" />

            <s:Button label="SHOW" click="show();"/>

      </s:VGroup>

</s:Application>

*source code :ObjectExample1.fxp

 

연관배열을 만드는 첫번째 방법은 Object클래스를 이용하는 것이고, 두번째 방법은 Array클래스를 이용하는 방법이 있습니다.

 

위의 예제에서 세가지 객체 capitalInfo, capitalInfo2, capitalInfo3들은 똑같은 Data를 가지고 있는 객체들입니다. 각기 다른방법으로 생성되어있습니다.

첫번째 객체 capitalInfo은 선언과 동시에 초기화 되어있습니다. 참고로 이와같이 선언과 동시에 초기화 하는 것은 객체리터럴이라 합니다.

두번째 객체 capitalInfo2은 Object클래스의 생성자를 이용하여 초기화 합니다. 주의하실점은 키값에 공백이 있어서는 안됩니다.

세번째 객체 capitalInfo는 Array클래스를 이용합니다. Array클래스를 이용할 경우 첫번째 객체처럼 객체리터럴을 사용할 수 없으며, Array클래스가 가지는 이점들, 속성등을 이용할 수는 없습니다. 특별히 좋은 점은 없다는 결론입니다.

* 연관배열을 만들 경우 Array를 사용하여 만들지 마시고, Object를 이용하세요. Array는 태생이 인덱스배열이기 때문에 권장하는 방법이 아닙니다. 자세한 내용은 검쉰님의 블로그에 잘 나와있습니다.

 

 

 

2. Dictionary클래스

 

지금까지 내용을 요약하면, "연관배열을 만드는 방법에는 Object클래스를 이용하는 방법과, Array클래스를 이용하는 방법이 있는데 Array클래스 보다 Object클래스를 이용하는 것을 권장한다." 입니다.

Object클래스로 연관배열은 만들경우 KEY값으로 문자열이 들어가는데, KEY값으로 문자열 뿐만 아니라 객체를 KEY값으로 할 수 있습니다. 그것이 바로 Dictionary클래스 입니다.

 

Dictionary 클래스는 객체유형을 키로 사용하여 요소를 구분할 수 있는 연관배열입니다.

 

 

Dictionay클래스는 Actionscript 3.0에 도입된 연관배열입니다.  특이한 점이 있다면 Dictionary클래스는 문자열이 아니라 객체를 키값으로 갖는다는 것입니다.

 

자세한 내용은 Reference를 보시면 자세히 나와있습니다.

 

내용의 핵심은 다음과 같습니다.

- Dictionary는 순서나 정렬이 되지 않은 정렬되지 않는 키/값 쌍 모음이다.

- Dictionary에 쓰이는 키 값으로 꼭 String타입이 아니더라도 됩다. 일반적으로 Object클래스의 인스턴스가 사용.

 

 

 

 

 

 

 

 

 다음은 Reference에 나와있는 간단한 예제입니다.

<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

                     xmlns:s="library://ns.adobe.com/flex/spark"

                     xmlns:mx="library://ns.adobe.com/flex/mx"

                     creationComplete="init();">

      <fx:Script>

            <![CDATA[

                 

                  private function init():void

                  {

                        var groupMap:Dictionary = new Dictionary();

                       

                        // 키로 사용할 객체

                        var spr1:Sprite = new Sprite();

                        var spr2:Sprite = new Sprite();

                        var spr3:Sprite = new Sprite();

                       

                        // 값으로 사용할 객체

                        var groupA:Object = new Object();

                        var groupB:Object = new Object();

                       

                        // 사전에 - 쌍을 만듭니다.

                        groupMap[spr1] = groupA;

                        groupMap[spr2] = groupB;

                        groupMap[spr3] = groupB;

                       

                        if(groupMap[spr1] == groupA)

                        {

                             trace("sprl1 is in groupA");

                        }

                        if(groupMap[spr2] == groupB)

                        {

                             trace("sprl2 is in groupB");

                        }

                        if(groupMap[spr3] == groupB)

                        {

                             trace("sprl3 is in groupB");

                        }

                  }

            ]]>

      </fx:Script>

</s:Application>

*source code :DictionaryExample.fxp

 

 

< 결과 > 

 

 

 

if문을 통해  Key에 저장되어 있는 Data를 확인할 수 있습니다. 그렇다면 사전에 저장되어있는 모든 Key와 Data를 출력해보겠습니다.

 

for ..in 루프를 통해 출력해보면 다음과 같습니다.

 

 

 for(var key:Object in groupMap)

 {

     trace(key, groupMap[key]);

 }

 

 

< 결과 >

 

Dictionary 객체의 값에 직접 액세스 하려면 for each ..in 루프를 사용합니다.

 

 

 for each(var item:Object in groupMap)

 {

     trace(item);

 } 

 

 

< 결과 >

 

 

 

 

 

 

 

3. 객체 키 및 메모리 관리

 

* 다음 내용은 Adobe Dictionary Reference 내용을 그대로 옮겨놓은 것입니다.

 

Adobe® Flash® Player 및 Adobe® AIR™에서는 가비지 컬렉션 시스템을 사용하여 더 이상 사용되지 않는 메모리를 복구합니다. 객체에 객체를 가리키는 참조가 없을 경우 객체는 가비지 컬렉션의 대상이 되며 다음 번 가비지 컬렉션 시스템 실행 시 메모리가 복구됩니다. 예를 들어 다음 코드는 새 객체를 만들어 변수 myObject에 객체에 대한 참조를 할당합니다.

 

var myObject:Object = new Object();

 

객체에 대한 참조가 남아 있는 한, 가비지 컬렉션 시스템에서는 객체가 사용하고 있는 메모리를 복구하지 않습니다. 다른 객체를 가리키거나 null 값으로 설정되는 등 myObject 값이 변경되면, 원래 객체에 의해 사용되던 메모리는 가비지 컬렉션의 대상이 됩니다. 그러나 원래 객체에 대한 다른 참조가 없는 경우에만 해당됩니다.

Dictionary 객체에서 myObject를 키로 사용하는 경우 원래 객체에 대한 다른 참조가 만들어집니다. 예를 들어 다음 코드에서는 객체에 대한 두 개의 참조 즉, myObject 변수 및 myMap 객체의 키를 만듭니다.

 

import flash.utils.Dictionary;

var myObject:Object = new Object();
var myMap:Dictionary = new Dictionary();
myMap[myObject] = "foo";

 

myObject로 참조되는 객체를 가비지 컬렉션 대상으로 만들려면 객체에 대한 참조를 모두 제거해야 합니다. 이 경우, 다음 코드와 같이 myObject 값을 변경하고 myMap에서 myObject 키를 삭제해야 합니다.

 

myObject = null;
delete myMap[myObject];

 

또는 Dictionary 생성자의 useWeakReference 매개 변수를 사용하여 사전 키를 모두 약한 참조로 만들 수 있습니다. 가비지 컬렉션 시스템에서는 약한 참조를 무시하므로 약한 참조만 있는 객체는 가비지 컬렉션의 대상이 됩니다. 예를 들어 다음 코드에서는 객체를 가비지 컬렉션 대상으로 만들기 위해 myMap에서 myObject 키를 삭제할 필요가 없습니다.

 

 import flash.utils.Dictionary;

var myObject:Object = new Object();
var myMap:Dictionary = new Dictionary(true);
myMap[myObject] = "foo";
myObject = null; // Make object eligible for garbage collection.

 

 

* 참고

- Dictionary API

- Associative Array API

- Dictionary Reference

- 해피나님의 블로그 - Flex(Actionscript) 에서 Object 와 Dictionary 에 대한 고찰

- 검쉰님의 블로그 - Array를 왜 Hash로 쓰나요? Object 놔두고.

- AS3 Dictionary Class vs. Array vs. Object!

AND