Coleções e estruturas de dados
Dados semelhantes podem normalmente ser tratados com mais eficiência quando armazenados e manipulados como uma coleção. Você pode usar a classe System.Array ou as classes dos namespaces System.Collections, System.Collections.Generic, System.Collections.Concurrent e System.Collections.Immutable para adicionar, remover e modificar elementos individuais ou um intervalo de elementos em uma coleção.
Há dois tipos principais de coleções; coleções genéricas e coleções não genéricas. Coleções genéricas são fortemente tipadas em tempo de compilação. Por isso, coleções genéricas normalmente oferecem melhor desempenho. Coleções genéricas aceitam um parâmetro de tipo quando são criadas e não exigem que você converta de e para o tipo Object ao adicionar ou remover itens da coleção. Além disso, há suporte para a maioria das coleções genéricas nos aplicativos da Windows Store. As coleções não genéricas armazenam itens como Object, exigem a conversão e a maioria não tem suporte para o desenvolvimento de aplicativos da Windows Store. No entanto, você pode ver as coleções não genéricas no código mais antigo.
A partir do .NET Framework 4, as coleções do namespace System.Collections.Concurrent fornecem operações thread-safe eficientes para acessar itens da coleção por meio de vários threads. As classes de coleção imutáveis do namespace System.Collections.Immutable (pacote NuGet) são inerentemente thread-safe, pois as operações são executadas em uma cópia da coleção original e a coleção original não pode ser modificada.
Recursos comuns de coleção
Todas as coleções fornecem métodos para adicionar, remover ou localizar itens na coleção. Além disso, todas as coleções que direta ou indiretamente implementam a interface ICollection ou a interface ICollection<T> compartilham estes recursos:
A capacidade de enumerar a coleção
As coleções do .NET implementam System.Collections.IEnumerable ou System.Collections.Generic.IEnumerable<T> para permitir a iteração na coleção. Um enumerador pode ser considerado um ponteiro móvel para qualquer elemento da coleção. A instrução foreach, in e a Instrução For Each...Next usam o enumerador exposto pelo método GetEnumerator e ocultam a complexidade de manipulação do enumerador. Além disso, qualquer coleção que implementa System.Collections.Generic.IEnumerable<T> é considerada um tipo passível de consulta e pode ser consultada com LINQ. Consultas LINQ fornecem um padrão comum para o acesso de dados. Elas são geralmente mais concisas e legíveis que loops
foreach
padrão e fornecem filtragem, classificação e agrupamento de recursos. Consultas LINQ também podem melhorar o desempenho. Para obter mais informações, consulte LINQ to Objects (C#), LINQ to Objects (Visual Basic), Parallel LINQ (PLINQ), Introdução a consultas LINQ (C#) e Operações básicas de consulta (Visual Basic).A capacidade de copiar o conteúdo da coleção para uma matriz
Todas as coleções podem ser copiadas para uma matriz usando o método CopyTo; no entanto, a ordem dos elementos na nova matriz se baseia na sequência na qual o enumerador os retorna. A matriz resultante é sempre unidimensional com um limite inferior de zero.
Além disso, muitas classes de coleção contêm os seguintes recursos:
Propriedades de capacidade e contagem
A capacidade de uma coleção é o número de elementos que ela pode conter. A contagem de uma coleção é o número de elementos que ela realmente contém. Algumas coleções ocultam a capacidade ou a contagem ou ambas.
A maioria das coleções se expande automaticamente em capacidade quando a capacidade atual é atingida. A memória é realocada e os elementos são copiados da coleção antiga para a nova. Isso reduz o código necessário para usar a coleção; no entanto, o desempenho da coleção pode ser afetado de forma negativa. Por exemplo, para List<T>, se Count for inferior a Capacity, a adição de um item será uma operação O(1). Se a capacidade precisar ser aumentada para acomodar o novo elemento, a adição de um item passará a ser uma operação O(
n
), em quen
é Count. A melhor maneira de evitar um desempenho ruim causado por várias realocações é definir a capacidade inicial para que seja o tamanho estimado da coleção.Uma BitArray é um caso especial; sua capacidade é a mesma que seu comprimento, que é o mesmo de sua contagem.
Um limite inferior consistente
O limite inferior de uma coleção é o índice do seu primeiro elemento. Todas as coleções indexadas nos namespaces System.Collections têm um limite inferior de zero, indicando que são indexados em 0. Array tem um limite inferior de zero por padrão, mas um limite inferior diferente pode ser definido ao criar uma instância da classe Matriz usando Array.CreateInstance.
Sincronização para acesso de vários threads (System.Collections somente classes).
Os tipos de coleções não genéricas no namespace System.Collections oferecem algum acesso thread-safe com sincronização, geralmente exposto por meio dos membros SyncRoot e IsSynchronized. Essas coleções são não thread-safe por padrão. Se você precisar de acesso com multithread escalável e eficiente para uma coleção, use uma das classes no namespace System.Collections.Concurrent ou considere usar uma coleção imutável. Para obter mais informações, veja Coleções thread-safe.
Escolher uma coleção
Em geral, você deve usar coleções genéricas. A tabela a seguir descreve alguns cenários comuns de coleção e as classes de coleção que você pode usar para esses cenários. Se você for inexperiente com coleções genéricas, esta tabela o ajudará a escolher a coleção genérica adequada para a tarefa.
Eu quero… | Opções de coleção genérica | Opções de coleção não genérica | Opções de coleção thread-safe ou imutável |
---|---|---|---|
Armazenar itens como pares chave/valor para consulta rápida por chave | Dictionary<TKey,TValue> | Hashtable (Um conjunto de pares chave/valor que são organizados com base no código hash da chave.) |
ConcurrentDictionary<TKey,TValue> ReadOnlyDictionary<TKey,TValue> ImmutableDictionary<TKey,TValue> |
Itens de acesso por índice | List<T> | Array ArrayList |
ImmutableList<T> ImmutableArray |
Usar itens primeiro a entrar, primeiro a sair (PEPS) | Queue<T> | Queue | ConcurrentQueue<T> ImmutableQueue<T> |
Usar dados último a entrar, primeiro a sair (UEPS) | Stack<T> | Stack | ConcurrentStack<T> ImmutableStack<T> |
Acessar itens em sequência | LinkedList<T> | Nenhuma recomendação | Nenhuma recomendação |
Receba notificações quando itens forem removidos da coleção ou adicionados a ela. (implementa INotifyPropertyChanged e INotifyCollectionChanged) | ObservableCollection<T> | Nenhuma recomendação | Nenhuma recomendação |
Uma coleção classificada | SortedList<TKey,TValue> | SortedList | ImmutableSortedDictionary<TKey,TValue> ImmutableSortedSet<T> |
Um conjunto de funções matemáticas | HashSet<T> SortedSet<T> |
Nenhuma recomendação | ImmutableHashSet<T> ImmutableSortedSet<T> |
Complexidade algorítmica de coleções
Ao escolher uma classe de coleção, vale a pena considerar as possíveis compensações no desempenho. Use a tabela a seguir para ter uma referência de comparação dos vários tipos de coleções mutáveis em complexidade algorítmica com os equivalentes imutáveis correspondentes. Geralmente, os tipos de coleções imutáveis têm um desempenho inferior, mas fornecem imutabilidade – o que costuma ser um benefício comparativo válido.
Mutável | Amortizado | Pior caso | Imutável | Complexidade |
---|---|---|---|---|
Stack<T>.Push |
O(1) | O(n ) |
ImmutableStack<T>.Push |
O(1) |
Queue<T>.Enqueue |
O(1) | O(n ) |
ImmutableQueue<T>.Enqueue |
O(1) |
List<T>.Add |
O(1) | O(n ) |
ImmutableList<T>.Add |
O(log n ) |
List<T>.Item[Int32] |
O(1) | O(1) | ImmutableList<T>.Item[Int32] |
O(log n ) |
List<T>.Enumerator |
O(n ) |
O(n ) |
ImmutableList<T>.Enumerator |
O(n ) |
Pesquisa de HashSet<T>.Add |
O(1) | O(n ) |
ImmutableHashSet<T>.Add |
O(log n ) |
SortedSet<T>.Add |
O(log n ) |
O(n ) |
ImmutableSortedSet<T>.Add |
O(log n ) |
Dictionary<T>.Add |
O(1) | O(n ) |
ImmutableDictionary<T>.Add |
O(log n ) |
Pesquisa de Dictionary<T> |
O(1) | O(1) – ou estritamente O(n ) |
Pesquisa de ImmutableDictionary<T> |
O(log n ) |
SortedDictionary<T>.Add |
O(log n ) |
O(n log n ) |
ImmutableSortedDictionary<T>.Add |
O(log n ) |
Uma List<T>
pode ser enumerada com eficiência por meio de um loop for
ou um loop foreach
. No entanto, uma ImmutableList<T>
não é eficiente em um loop for
, devido ao tempo de O(log n
) do indexador. A enumeração de uma ImmutableList<T>
por meio de loop foreach
usando é eficiente porque ImmutableList<T>
usa uma árvore binária para armazenar os dados em vez de uma matriz simples como usado por List<T>
. Uma matriz pode ser indexada muito rapidamente, enquanto uma árvore binária precisa ser percorrida até que o nó com o índice desejado seja encontrado.
Além disso, SortedSet<T>
tem a mesma complexidade que ImmutableSortedSet<T>
. Isso porque ambos usam árvores binárias. Obviamente, a diferença significativa é que ImmutableSortedSet<T>
usa uma árvore binária imutável. Como ImmutableSortedSet<T>
também oferece uma classe System.Collections.Immutable.ImmutableSortedSet<T>.Builder que permite a mutação, é possível ter imutabilidade e desempenho.
Tópicos Relacionados
Título | Descrição |
---|---|
Selecionando uma classe de coleção | Descreve as diferentes coleções e ajuda a selecionar uma para o seu cenário. |
Tipos de Coleção de Uso Comum | Descreve os tipos de coleção genérica e não genérica normalmente usadas, tais como System.Array, System.Collections.Generic.List<T>, e System.Collections.Generic.Dictionary<TKey,TValue>. |
Quando Usar Coleções Genéricas | Descreve o uso de tipos de coleção genérica. |
Comparações e Classificações Dentro de Coleções | Discute o uso de comparações de igualdade e comparações de classificação em coleções. |
Tipos de Coleção Sorted | Descreve as características e o desempenho de coleções classificadas |
Tipos de Coleção de Tabela de Hash e Dicionário | Descreve os recursos de tipos de dicionário baseado em hash genérico e não genérico. |
Coleções Thread-Safe | Descreve os tipos de coleção, tais como System.Collections.Concurrent.BlockingCollection<T> e System.Collections.Concurrent.ConcurrentBag<T> que dão suporte a acesso simultâneo seguro e eficiente de vários threads. |
System.Collections.Immutable | Apresenta as coleções imutáveis e fornece links para os tipos de coleção. |
Referência
System.Array System.Collections System.Collections.Concurrent System.Collections.Generic System.Collections.Specialized System.Linq System.Collections.Immutable