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

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

다른 데이터 구조도 많이 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 Count및 Item(0부터 시작하는 인덱스를 사용하여 항목에 액세스) 속성입니다. IDictionary반면에 해시 가능 인덱스로 항목에 액세스 할 수 있습니다.

  • Array, ArrayList그리고 List모든 구현 IList. Dictionary, SortedDictionary및 Hashtable구현 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)는 무엇입니까? MSDN 은 List(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.