콘텐츠로 건너뛰기
Home » 컬렉션(Collection)

컬렉션(Collection)

  • by
컬렉션(Collection)

컬렉션(Collection)

컬렉션은 간단히 말해 데이터 모음(자료구조) 이다.
즉 우리가 잘 아는 배열이나 스택,큐 등을 C#에서 컬렉션이라는 이름으로 제공하는 것이다.

C#의 컬렉션을 사용하기 위해서는 컬렉션 네임 스페이스를 참조 해야합니다.
예) using System.Collections;

이렇게 컬렉션 네임스페이스 사용을 선언한 후에는 원하는 컬렉션을 생성하여 사용할수 있다. C#에서 제공하는 대표적인 컬렉션은 ArrayList, Queue, Stack, Hashtable 등이 있으며 간단히 살펴 보면 다음과 같습니다.

ArrayList

ArrayList는 배열과 비슷한 컬렉션이다.
배열처럼 [] 인덱스로 컬렉션 요소에 접근이 가능하고, 특정 요소를 바로 읽고 쓸수 있다. 하지만 보통의 배열을 선언할때 배열 크기를 지정해야 하는 것과 달리 ArrayList는 크기 지정없이 바로 사용할수 있다.
또한 ArrayList 컬렉션 하나로 모든 타입의 변수를 담을수 있다는 장점이 있다.
(ArrayList 뿐만 아니라 C#에서 제공하는 모든 컬렉션은 모든 타입의 변수를 담을수 있다. 어떤 타입으로도 받을수 있는 object 으로 저장되기 때문이다.)

using System;
using System.Collections;
namespace Test_Collection {
    class Program {
        static void Main(string[] args) {
            ArrayList list = new ArrayList();
            list.Add(10); // [0] 10
            list.Add(20); // [1] 20
            list.Add(30); // [2] 30
            list.RemoveAt(1); // [1] 삭제
            list.Insert(1, 2.3 f); // [1] 에 2.3 추가 
            list.Add("여러분~"); // [3] "여러분~"
            list.Add("공부 열심히 하세요~~"); // [4] "공부 열심히 하세요~~"
            // 컬레션의 모든 요소를 object 타입으로 저장된다.
            foreach(object obj in list) {
                Colsole.Write("{0}", obj);
                Colsole.WriteLine();
            }
        }
    }
}

ArrayList 에서 주로 사용하는 함수들은 Add(), Insert(), Remove(), RemoveAt()등 입니다.
Add()와 Insert()는 데이터를 추가해주는 함수인데, Add()는 리스트의 마지막 요소 다음으로 데이터를 추가하는 것이도, Insert(위치, 값)는 원하는 위치에 값을 삽입하는 것이다.

Remove와RemoveAt은 데이터를 제거하는 함수로, Remove(값)는 매개변수로 전달된 값을 찾아 삭제하는것이고 RemoveAt(위치)는 리스트의 해당 인덱스를 찾아 제거한다.
[위치=>인덱스, 값=>데이터]

Queue (First In First Out)

큐는 선입선출(FIFO)의 자료구조다. 선입선출이란 데이터들이 입력되어 차례 차례 줄을 서면서 먼저 들어온 데이터(선입)가 먼저 출력되는 방식(선출)을 말한다.

(큐에서의 데이터 입력을 Enqueue 라고 하며 데이터 출력을 Dequeue 라고 한다.)

큐는 ArrayList 처럼 원하는 위치에 데이터를 입,출력하는 것이 불가능합니다.
위의 그림을 참고하세요.

using System;
using System.Collections;
namespace Test_Collection {
    class Program {
        static void Main(string[] args) {
            Queue que = new Queue();
            que.Enqueue(10); // 10
            que.Enqueue(20); // 10,20
            que.Enqueue(30); // 10,20,30
            que.Dequeue(); // 20,30
            que.Enqueue(4.4 f); // 20,30,4.4
            que.Dequeue(); // 30,4.4
            que.Enqueue("ABC"); // 30,4.4,ABC
            while (que.Count > 0) {
                Colsole.WriteLine(que.Dequeue());
            }
        }
    }
}

Stack (Last In First Out)

(Stack 에서는 데이터 입력을 Push라고 하고, 데이터 출력을 Pop이라 한다.)
using System;
using System.Collections;
namespace Test_Collection {
    class Program {
        static void Main(string[] args) {
            Stack stack = new Stack();
            stack.Push(10); // 10
            stack.Push(20); // 10,20
            stack.Push(30); // 10,20,30
            stack.Pop(); // 10,20
            stack.Pop(); // 10
            stack.Push(4.4 f); // 10,4.4
            stack.Push("ABC"); // 10,4.4,ABC
            while (stack.Count > 0) {
                Colsole.WriteLine(stack.Pop());
            }
        }
    }
}

Hashtable

해쉬 테이블은 키(key)와 값(value)을 가진 데이터를 저장하는 자료구조이다.

해쉬테이블은 마치 영한 사전 프로그램에서 [Apple] 이라는 단어를 치며 [사과] 라는 뜻이 출력되는 것과 같다.

예) Apple -> 사과, Banana -> 바나나, Orange -> 오렌지 여기서 “Apple” 이 키가 되고, “사과” 가 값이 되는것이다. 어떻게 보면 배열과 접근방식이 유사하다.

배열에서 인덱스를 가지고 데이터에 접근하는데, (예: Array[0] = 1 …) 해쉬테이블에서는 키를 가지고 값에 접근한다. (예: Ht[“Apple”] = “사과” …)

그리고 해싱(Hashing: 키값으로 주소를 산출하는 알고리즘)으로 데이터에 접근하기 때문에 탐색 속도가 거의 소요되지 않는 장점을 가진다. (배열에 준하는 탐색 속도)

이에 더해서 배열은 인덱스로 숫자만을 사용하지만 해쉬 테이블은 키 값으로 어떤 타임(int, float, string, class) 이든 사용할수 있기 때문에 활용도가 높다

using System;
using System.Collections;
namespace Test_Collection {
    class Program {
        static void Main(string[] args) {
            Hashtable ht = new Hashtable();
            ht["Apple"] = "사과";
            ht["Banana"] = "바나나";
            ht["Orange"] = "오렌지";
            Console.WriteLine(ht["Apple"]);
            Console.WriteLine(ht["Banana"]);
            Console.WriteLine(ht["Orange"]);
        }
    }
}

컬렉션의 성능 문제

C# 컬렉션의 장점은 어떤 타입의 데이터든지 전부 담을수 있다는 것입니다.
하지만 이러한 장점에는 역시 한계가 있다.
컬렉션은 데이터를 받으면 어떤 형식이든지 object 형식으로 박싱(Boxing) 되어 저장된다.
그리고 데이터에 접근하여 사용할 때에는 원래의 데이터 형식으로 언박싱(Unboxing)이 된다.

결국 컬렉션에 데이터의 입,출력이 있으면, 그때마다 박싱과 언박싱이 계속해서 발생하게 되고, 데이터가 많아질수록 성능에 상당한 저하가 생기게 된다.

이러한 문제 때문에 보통의 컬렉션 보다는 일반화 컬렉션(4장)의 사용을 해야할때가 있습니다.

도움말

프로그램을 실행시키면 운영체제는 우리가 실행시킨 프로그램을 위해 메모리 공간을 할당하는데, 할당되는 메모리 공간은 크게 스택, 힙, 데이터 영역으로 나뉘어집니다.
이러한 메모리 공간이 어떠한 용도로 언제, 어디서 할당되는 알아야 합니다.
할당시기는 프로그램이 실행될때 마다 입니다.
할당 장소는 메인 메모리 이며, 프로그램 실행시 필요한 메모리 공간에 지역,전역변수 선언 위한 할당을 하게 되는데요
데이터 영역에는 전역 및 Static 변수의 값을 위한 메모리 할당을 하며, 프로그램 시작과 동시에 할당되고, 프로그램 종료되어야 메모리에서 소멸됩니다.
스택 영역에는 함수 호출시 생성되는 지역변수와 매개 변수가 저장되는 영역입니다.
함수 호출이 완료되면 사라집니다.
(컴파일시 결정되어 사용)
힙 영역이란 필요에 의해 동적으로 메모리를 할당하는 영역입니다.
솔직히 데이터영역과 스택만 있으면 가능해보일수도 있으나 동적으로 메모리할당이 필요한 이유는 다음과 같습니다.
(런타임시 유동적으로 사용)
정상적인 배열선언
int array[10]; 이라고 선언한 경우
스택 영역에 할당될 메모리의 크기는 컴파일 하는 동안 결정될수 있습니다.
비정상적 배열선언
int i = 10;
int array[i];
이 상태로 컴파일을 할경우 변수 i 의 메모리 할당은 가능하지만
array[i] 경우는 컴파일러가 array[10] 으로 인식할수가 없습니다.
이렇게 사용자 요구에 맞게 동적 할당을 할수있는 힙 영역을 사용하는것입니다.

할당해야 할 메모리의 크기를 프로그램이 실행되는 동안 결정해야 하는 경우(런 타임) 유용하게 사용되는 공간을 얘기합니다.

댓글 남기기