.NET 데이터 구조 : ArrayList, List, HashTable, Dictionary, SortedList, SortedDictionary — 속도, 메모리 및 각각 사용시기?


213

.NET에는 많은 복잡한 데이터 구조가 있습니다. 불행히도, 그들 중 일부는 매우 유사하며, 언제 사용하고 언제 사용해야하는지 잘 모르겠습니다. 내 C # 및 Visual Basic 책의 대부분은 어느 정도 그들에 대해 이야기하지만 실제로는 실제로 자세히 다루지 않습니다.

Array, ArrayList, List, Hashtable, Dictionary, SortedList 및 SortedDictionary의 차이점은 무엇입니까?

열거 할 수있는 것은 무엇입니까 (IList- 'foreach'루프를 수행 할 수 있습니까)? 어느 것이 키 / 값 쌍 (IDict)을 사용합니까?

메모리 풋 프린트는 어떻습니까? 삽입 속도? 검색 속도?

언급 할만한 다른 데이터 구조가 있습니까?

메모리 사용 및 속도 (Big-O 표기법)에 대한 자세한 내용을 계속 찾고 있습니다.


12
이 질문을 분리해야합니다. 당신은 20 가지 다른 것을 요구하고 있으며, 그중 절반은 간단한 Google 검색이 대답 할 수 있습니다. 좀 더 구체적으로 설명하십시오. 귀하의 질문이 너무 흩어져있을 때 도움이되지 않습니다.

33
나는 그것을 깨뜨리는 것에 대해 생각했지만 누군가 가이 모든 대답을 한 곳으로 통합 할 수 있음을 깨달았습니다. 실제로 누군가가 모든 것을 프로파일 링하는 테이블을 생각 해낼 수 있다면이 사이트에서 훌륭한 리소스가 될 수 있습니다.
Pretzel

9
이 질문을 위키로 바꿀 수 있습니까?
BozoJoe

1
이 MSDN 기사는 트리, 그래프 및 세트, 광범위한 데이터 구조 조사
Ryan Fisher

1
라이언, 그 링크의 기사는 14 세입니다 (포스트 시점 12). 나는 지난 주에 나 자신을 읽고 있습니다. 그러나 그들은 또한 최신 기술을 포함하지 않으며 필사적으로 업데이트가 필요합니다. 그리고 더 많은 성능 지표와 예제.
htm11h

답변:


156

내 머리 꼭대기에서 :

  • Array*-구식 메모리 배열을 나타냅니다 type[]. 일반 배열 의 별칭과 같습니다 . 열거 할 수 있습니다. 자동으로 성장할 수 없습니다. 나는 매우 빠른 삽입 및 검색 속도를 가정합니다.

  • ArrayList-자동으로 성장하는 어레이. 더 많은 오버 헤드를 추가합니다. 열거 할 수 있습니다. 아마 일반 배열보다 느리지 만 여전히 꽤 빠릅니다. 이들은 .NET에서 많이 사용됩니다.

  • List-내 즐겨 찾기 중 하나-제네릭과 함께 사용할 수 있으므로 예를 들어 강력한 형식의 배열을 사용할 수 있습니다 List<string>. 그 외에는ArrayList

  • Hashtable-평범한 오래된 해시 테이블. O (1)에서 O (n)까지의 최악의 경우입니다. value 및 keys 속성을 열거하고 키 / val 쌍을 수행 할 수 있습니다.

  • Dictionary -위와 동일하게 제네릭을 통해 강력하게 입력됩니다. Dictionary<string, string>

  • SortedList-정렬 된 일반 목록. 물건을 넣을 위치를 알아야하기 때문에 삽입 속도가 느려졌습니다. 열거 할 수 있습니다. 아마도 검색 할 필요가 없기 때문에 검색시 동일하지만 삭제는 평범한 이전 목록보다 느립니다.

내가 사용하는 경향 ListDictionary모든 시간을 - 당신이 그들을 강하게 제네릭 타입 사용하기 시작하면, 그 정말 열심히 표준 제네릭이 아닌 사람에게 돌아갑니다.

다른 데이터 구조도 많이 KeyValuePair있습니다. 흥미로운 것들을 수행하는 데 사용할 SortedDictionary수 있고 유용한 것도 있습니다.


3
해시 테이블은 O (1), (충돌)와 최악의 경우 O (N) 일 수있다
저스틴 Bozonier

7
여기에 추가해야 할 다른 데이터 구조가 많이 있습니다. LinkedList, Skip List, Stack, Queue, Heap, Trees, Graphs와 같은 이것 또한 매우 중요한 데이터 구조입니다.
DarthVader

2
ConcurrentDictionary는 4.0 스레드 안전과 일반 사전을 제공 닷넷에 추가
Harindaka

2
또한 BlockingCollection <T>는 스레드 안전 생산자 / 소비자 구현을 제공합니다
Harindaka

7
ArrayList가상 메소드를 사용하지만 List<T>그렇지 않습니다. 표준 컬렉션과 사용자 지정 컬렉션의 기본 클래스로 ArrayList대체되었습니다 . 로 대체되었습니다 . 나는 피하는 것이 좋습니다 및 새로운 코드. List<T>Collection<T>HashtableDictionary<TKey, TValue>ArrayListHashtable
Sam Harwell

29

가능하면 제네릭을 사용하십시오. 여기에는 다음이 포함됩니다.

  • ArrayList 대신 List
  • HashTable 대신 사전

24

먼저 .NET의 모든 컬렉션은 IEnumerable을 구현합니다.

둘째, 제네릭이 프레임 워크 버전 2.0에 추가 되었기 때문에 많은 컬렉션이 중복되었습니다.

따라서 일반 컬렉션은 기능을 추가 할 가능성이 있지만 대부분 다음과 같습니다.

  • List는 일반적인 ArrayList 구현입니다.
  • 사전은 Hashtable의 일반적인 구현입니다

배열은 고정 된 크기의 모음으로, 주어진 색인에 저장된 값을 변경할 수 있습니다.

SortedDictionary는 키를 기준으로 정렬 된 IDictionary입니다. SortedList는 필수 IComparer를 기준으로 정렬 된 IDictionary입니다.

따라서 IDictionary 구현 (KeyValuePair를 지원하는 구현)은 다음과 같습니다. * Hashtable * Dictionary * SortedList * SortedDictionary

.NET 3.5에 추가 된 또 다른 컬렉션은 해시 셋입니다. 세트 조작을 지원하는 콜렉션입니다.

또한 LinkedList는 표준 연결 목록 구현입니다 (목록은 더 빠른 검색을위한 배열 목록입니다).


20

다음은 몇 가지 일반적인 팁입니다.

  • foreach구현하는 유형에 사용할 수 있습니다 IEnumerable. IList기본적으로 IEnumberablewith CountItem(0부터 시작하는 인덱스를 사용하여 항목에 액세스) 속성입니다. IDictionary반면에 해시 가능 인덱스로 항목에 액세스 할 수 있습니다.

  • Array, ArrayList그리고 List모든 구현 IList. Dictionary, SortedDictionaryHashtable구현 IDictionary.

  • .NET 2.0 이상을 사용하는 경우 언급 된 유형의 일반 대응 물을 사용하는 것이 좋습니다.

  • 이러한 유형에 대한 다양한 작업의 시간 및 공간 복잡성에 대해서는 해당 설명서를 참조하십시오.

  • .NET 데이터 구조는 System.Collections네임 스페이스에 있습니다. 추가 데이터 구조를 제공하는 PowerCollection 과 같은 형식 라이브러리가 있습니다 .

  • 데이터 구조를 완전히 이해하려면 CLRS 와 같은 리소스를 참조하십시오 .


1
에서 MSDN 하지 IList의 -, IDictionnary 구현 sortedList 것 같아
하임 Bendanan

결정된. 의견 주셔서 감사합니다. SortedList는 키 / 값 목록을 유지하므로 기본적으로 사전의 데이터를 나타냅니다. 내가 처음 답을 쓸 때이 수업이 어떻게 진행되었는지 기억하지 마십시오.
blackwing

9

.NET 데이터 구조 :

ArrayList와 List가 실제로 다른 이유에 대한 대화

배열

한 사용자가 말했듯이 배열은 "구식"컬렉션입니다 (예, 배열은의 일부는 아니지만 컬렉션으로 간주 됨 System.Collections). 그러나 다른 컬렉션, 즉 제목에 나열한 컬렉션 (여기서는 ArrayList 및 List (Of T))과 비교하여 배열에 대해 "오래된 학교"란 무엇입니까? 배열을보고 기본 사항부터 시작하겠습니다.

우선 Microsoft .NET의 어레이 는 "논리적으로 관련된 여러 항목을 단일 컬렉션으로 취급 할 수있는 메커니즘"입니다 (링크 된 기사 참조). 그게 무슨 뜻이야? 배열은 개별 주소 (요소)를 순차적으로 메모리에 시작 주소가있는 순서대로 저장합니다. 배열을 사용하면 해당 주소에서 시작하여 순차적으로 저장된 요소에 쉽게 액세스 할 수 있습니다.

그 외에도 101 개의 공통 개념을 프로그래밍하는 것과 달리 배열은 실제로 매우 복잡 할 수 있습니다.

배열은 단일 차원, 다차원 또는 들쭉날쭉 한 것일 수 있습니다 (들쭉날쭉 한 배열은 읽을 가치가 있습니다). 배열 자체가 동적 아니다 : 초기화되면, 어레이 N의 크기를 보유하기 위해서 충분한 공간 N 객체들의 수. 배열의 요소 수는 늘어나거나 줄어들 수 없습니다. Dim _array As Int32() = New Int32(100)배열이 100 개의 Int32 기본 유형 객체를 포함 할 수 있도록 메모리 블록에 충분한 공간을 예약합니다 (이 경우 배열은 0을 포함하도록 초기화 됨). 이 블록의 주소는로 반환됩니다 _array.

이 기사에 따르면 CLS ( 공용 언어 사양 )에서는 모든 배열이 0부터 시작해야합니다. .NET의 배열은 0이 아닌 배열을 지원합니다. 그러나 이것은 덜 일반적입니다. 제로 기반 어레이의 "공통성"의 결과로 Microsoft는 성능을 최적화하는많은 시간을 보냈습니다 . 따라서 단일 차원의 0부터 시작하는 (SZ) 배열은 "특별한"배열이며 실제로는 다차원과 달리 배열의 최상의 구현입니다. SZ에는 배열을 조작하기위한 특정 중개 언어 명령어가 있기 때문입니다.

배열은 항상 참조에 의해 전달됩니다 (메모리 주소로)-중요한 배열 퍼즐 조각입니다. 경계 검사를 수행하는 동안 (오류가 발생 함) 배열에서 경계 검사를 비활성화 할 수도 있습니다.

다시 말하지만 배열에 대한 가장 큰 장애는 크기를 조정할 수 없다는 것입니다. 그것들은 "고정 된"용량을 가지고 있습니다. 히스토리에 ArrayList 및 List (Of T) 소개 :

ArrayList-일반이 아닌 목록

ArrayList를은 (함께 List(Of T)- 몇 가지 중요한 차이가 있지만, 여기에, 나중에 설명) - 아마도 (넓은 의미에서) 컬렉션의 다음뿐만 아니라 최고의 생각이다. ArrayList는 IList ( 'ICollection'의 자손) 인터페이스 에서 상속합니다 . ArrayLists는 자체이다 부피가 더 필요 - 오버 헤드 - 목록보다.

IList구현시 ArrayList를 고정 크기 목록 (예 : Arrays)으로 처리 할 수 ​​있습니다. 그러나 ArrayLists에 의해 추가 된 추가 기능 외에,이 경우 ArrayLists (Array보다) 크기가 고정되어있는 ArrayLists를 사용하면 실질적으로 이점이 없습니다.

내 독서에서 ArrayLists는 들쭉날쭉해질 수 없습니다. "다차원 배열을 요소로 사용하는 것은 지원되지 않습니다". 다시, ArrayLists의 관에 또 다른 손톱. ArrayLists는 또한 "유형"이 아닙니다. 즉, 모든 것 아래에서 ArrayList는 단순히 객체의 동적 배열입니다 Object[]. 이것은 ArrayLists를 구현할 때 많은 복싱 (암시 적) 및 언 박싱 (명시 적)이 필요하며 다시 오버 헤드에 추가됩니다.

불확실한 생각 : 나는 ArrayLists가 Arrays에서 List-type Collections로 이동하려는 시도에 대한 나쁜 자식 개념의 자식이라는 것을 교수들 중 한 사람으로부터 읽거나 들었다는 것을 기억합니다. 컬렉션과 관련하여 추가 개발이 완료되었으므로 더 이상 최선의 선택이 아닙니다.

List (Of T) : ArrayList가 된 (및 희망)

메모리 사용량의 차이는 (INT32의) 목록이 56 %를 소비 덜 같은 기본 유형을 포함하는 ArrayList에 비해 메모리 곳으로 크게 충분하다 (8메가바이트 위의 신사의 연결 시연에서 19메가바이트 대 : 다시 연결 여기에 ) - 비록 이는 64 비트 시스템에 의해 복합 된 결과입니다. 이 차이점은 실제로 두 가지를 보여줍니다. 첫 번째 (1), 박스형 Int32 유형 "object"(ArrayList)는 순수한 Int32 기본 유형 (List)보다 훨씬 큽니다. 둘째, 64 비트 시스템의 내부 작업으로 인해 차이가 기하 급수적으로 증가합니다.

차이점은 무엇이며 List (Of T)는 무엇입니까? MSDNList(Of T)"... 인덱스로 액세스 할 수있는 강력한 형식의 개체 목록"으로 정의합니다 . 여기서 "강력한 형식의"비트가 중요합니다. List (Of T)는 형식을 '인식'하고 개체를 해당 형식으로 저장합니다. 따라서 는 형식이 아닌 형식 Int32으로 저장됩니다 . 이것은 권투와 박스 해제로 인한 문제를 제거합니다.Int32Object

MSDN은이 차이가 기본 형식을 저장하고 참조 형식을 저장할 때만 발생한다고 지정합니다. 너무 큰 차이는 500 개 이상의 요소에서 실제로 발생합니다. 더 흥미로운 점은 MSDN 설명서에 "ArrayList 클래스를 사용하는 대신 List (Of T) 클래스의 형식 별 구현을 사용하는 것이 유리하다는 것입니다."

본질적으로 List (Of T)는 ArrayList이지만 더 좋습니다. ArrayList의 "일반적인"항목입니다. ArrayList와 마찬가지로 정렬 될 때까지 정렬되지 않을 수도 있습니다 (그림 참조). List (Of T)에도 일부 기능이 추가되었습니다.



3

그들은 지능적으로 잘 설명되어 있습니다. System.Collections를 입력하십시오 . 또는 System.Collections.Generics (선호) 및 사용 가능한 항목에 대한 간단한 설명과 목록이 제공됩니다.


3

해시 테이블 / 사전은 O (1) 성능으로, 성능이 크기의 함수가 아님을 의미합니다. 알고 있어야합니다.

편집 : 실제로 Hashtable / Dictionary <> 조회의 평균 시간 복잡도는 O (1)입니다.


5
"성능"과 같은 것은 없습니다. 복잡성은 운영에 달려 있습니다. 예를 들어, Dictionary <>에 n 개의 요소를 삽입하면 리 해싱으로 인해 O (1)이되지 않습니다.
Ilya Ryzhenkov

2
참고로, 리 해싱을 사용하더라도 Dictionary는 여전히 O (1)입니다. 사전이 확장되기 직전에 시나리오를 고려하십시오. 마지막 확장 이후에 추가 된 요소 중 절반은 해시 된 것입니다. 나머지 절반이 해시됩니다. 그 중 나머지 절반, 세 번 등. 각 요소에서 수행되는 평균 해싱 작업 수는 1 + 1 / 2 + 1 / 4 + 1 / 8 ... = 2입니다. 확장 직후의 상황은 본질적으로 동일하지만 모든 요소가 한 번 더 해시됩니다 (따라서 평균 해시 수는 3입니다). 다른 모든 시나리오는 그 사이에 있습니다.
supercat

3

일반 컬렉션은 특히 많은 항목을 반복 할 때 비 일반적인 컬렉션보다 성능이 우수합니다. 더 이상 권투 및 언 박싱이 발생하지 않기 때문입니다.


2

고주파 체계적인 거래 엔지니어링을위한 Hashtable vs Dictionary에 대한 중요한 참고 사항 : Thread Safety Issue

Hashtable은 여러 스레드에서 사용할 수 있도록 스레드 안전합니다. 사전 공개 정적 멤버는 스레드로부터 안전하지만 모든 인스턴스 멤버가 그렇게 보장되지는 않습니다.

따라서 Hashtable은 이와 관련하여 '표준'선택으로 남아 있습니다.


이것은 부분적으로 사실입니다. 이 기능 Hashtable은 한 명의 작성자와 여러 명의 독자 만 동시에 사용할 수 있습니다. 반면에 Dictionary동시에 수정되지 않는 한 여러 판독기와 함께 사용하는 것이 안전 합니다.
Bryan Menard

명확히. 그러나 거래 공간에서 라이브 마켓 데이터를 동시에 읽고 추가 된 항목이 포함 된 분석을 실행하고 있습니다. 그것은 또한 얼마나 많은 상인이 시스템을 사용하고 있는지에 달려 있습니다-그것이 당신이라면, 그것은 중요하지 않습니다.
Rob

1
.NET 4.0은 ConcurrentDictionary <TKey, TValue>를 제공합니다
Rob

1

제네릭 컬렉션과 제네릭이 아닌 컬렉션 간에는 미묘한 차이가 있습니다. 그들은 단지 다른 기본 데이터 구조를 사용합니다. 예를 들어, Hashtable은 한 명의 작성자가 여러 독자를 동기화하지 않고 보장합니다. 사전은 없습니다.


1

가장 인기있는 C # 데이터 구조 및 컬렉션

  • 정렬
  • 배열 목록
  • 명부
  • 연결 목록
  • 사전
  • 해시 세트
  • 스택
  • 정렬 된 목록

C # .NET 에는 다양한 데이터 구조가 있습니다. 예를 들어 가장 일반적인 데이터 구조 중 하나는 Array입니다. 그러나 C #에는 더 많은 기본 데이터 구조가 제공됩니다. 사용할 올바른 데이터 구조를 선택하는 것은 체계적이고 효율적인 프로그램 작성의 일부입니다.

이 기사에서는 C # .NET 3.5에 도입 된 새로운 구조를 포함하여 내장 된 C # 데이터 구조를 살펴 보겠습니다. 이러한 많은 데이터 구조는 다른 프로그래밍 언어에 적용됩니다.

정렬

가장 단순하고 가장 일반적인 데이터 구조는 배열입니다. AC # 배열은 기본적으로 개체 목록입니다. 그 특징을 정의하는 것은 모든 객체가 동일한 유형 (대부분의 경우)이며 특정 수의 객체가 있다는 것입니다. 배열의 특성상 목록 내 위치 (인덱스라고도 함)에 따라 요소에 매우 빠르게 액세스 할 수 있습니다. AC # 배열은 다음과 같이 정의됩니다.

[object type][] myArray = new [object type][number of elements]

몇 가지 예 :

 int[] myIntArray = new int[5];
 int[] myIntArray2 = { 0, 1, 2, 3, 4 };

위의 예에서 볼 수 있듯이 요소가 없거나 기존 값 집합을 사용하여 배열을 초기화 할 수 있습니다. 배열에 값을 삽입하는 것은 적합한 한 간단합니다. 어레이의 크기보다 많은 요소가있을 경우 작업이 비용이 많이 들며이 시점에서 어레이를 확장해야합니다. 기존의 모든 요소를 ​​더 큰 새로운 배열로 복사해야하므로 시간이 오래 걸립니다.

배열 목록

C # 데이터 구조 인 ArrayList는 동적 배열입니다. 그 의미는 ArrayList가 모든 양의 객체와 유형을 가질 수 있다는 것입니다. 이 데이터 구조는 배열에 새 요소를 추가하는 프로세스를 단순화하도록 설계되었습니다. 후드 아래에서 ArrayList는 공간이 부족할 때마다 크기가 두 배가되는 배열입니다. 내부 배열의 크기를 두 배로 늘리는 것은 장기적으로 요소 복사의 양을 줄이는 매우 효과적인 전략입니다. 우리는 여기서 그 증거에 들어 가지 않을 것입니다. 데이터 구조는 사용이 매우 간단합니다.

    ArrayList myArrayList = new ArrayList();
    myArrayList.Add(56);
    myArrayList.Add("String");
    myArrayList.Add(new Form());

ArrayList 데이터 구조의 단점은 검색된 값을 원래 유형으로 다시 변환해야한다는 것입니다.

int arrayListValue = (int)myArrayList[0]

소스 및 자세한 정보는 여기에서 찾을 수 있습니다 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.