Com certeza você já precisou lidar com dados e optou por usar List, seja por toda a praticidade que esta classe proporciona ou por ser uma das mais difundidas. Uma das perguntas que eu mais gosto de me fazer quando estou programando é: por que vou usar isto aqui? Essa é uma das perguntas que vamos responder agora no segundo artigo da série sobre coleções.
Definindo a List
Como vimos no artigo anterior, a recomendação é usar coleções genéricas, então encontramos a classe List<T>
no namespace System.Collections.Generic. A List<T>
representa uma lista fortemente tipada de objetos que podem ser acessados por índice e possui métodos para pesquisar, classificar e manipular as listas. Por baixo dos panos, a List<T>
é um array unidimensional que começa em índice zero.
Utilizando a List<T>
Para inicializar uma lista do tipo Aluno, escrevemos assim:
List<Aluno> alunos = new List<Aluno>();
Ao utilizarmos o construtor sem parâmetros, iremos criar uma lista com a capacidade padrão, que é 4. Após a inicialização, podemos adicionar itens à lista usando o método Add() passando o objeto aluno como parâmetro, assim:
alunos.Add(new Aluno { Id = 1, Nome = "Thaise" });
Agora aqui é a dica de ouro para otimizar seu código usando List<T>
com uma grande quantidade de itens! Se não definirmos a capacidade, o .NET vai criar uma com capacidade para até 4 itens, que é o padrão. Toda vez que um item é adicionado, é verificado se a capacidade da lista comporta mais um item. Caso a capacidade seja menor que a quantidade de itens mais 1, que estamos tentando adicionar, será criada uma nova lista com a capacidade duplicada e os itens da lista atual serão copiados para a nova.
Por exemplo: no nosso código acima, criamos uma lista de alunos usando o construtor sem parâmetros e adicionamos um aluno nela. Neste momento, temos uma lista de alunos com capacidade para até 4 itens e um item adicionado. Agora vamos inserir mais 3 itens:
alunos.Add(new Aluno { Id = 2, Nome = "Ana" });
alunos.Add(new Aluno { Id = 3, Nome = "Cristiano" });
alunos.Add(new Aluno { Id = 4, Nome = "Maggie" });
Neste momento ainda temos uma lista com capacidade para até 4 itens e agora com 4 itens. Isso significa que estamos utilizando a capacidade máxima. Quando adicionarmos mais um item, a verificação para saber se a lista comporta mais um item vai retornar negativa. Para comportar mais itens, será criada uma nova lista com a capacidade duplicada da atual, que será 8. Os itens da lista atual serão copiados para a nova e aí sim será adicionado o quinto item, fazendo com que ainda sobre 3 posições. Essa lógica é repetida quantas vezes forem necessárias para comportar os itens que estamos adicionando e assim vamos criando listas com capacidade de 4, 8, 16, 32, 64, 128... E as listas antigas simplesmente são deixados para trás e ficam a cargo do Garbage Collector fazer a limpeza delas. Dependendo da quantidade, isso gera pressão desnecessária no GC afetando a performance da sua aplicação. Entenderam a importância de definirmos a capacidade? Para isso, basta usar o construtor com o parâmetro int:
List<Aluno> alunos = new List<Aluno>(500);
Conclusão
Usar a capacidade na inicialização da lista é uma abordagem extremamente simples mas muito útil ao lidar com grande quantidade dados. "Ah, mas e quando eu não sei quantos itens serão adicionados?" Aqui entra a importância de entendermos a volumetria da aplicação que estamos trabalhando. A ideia não é acertarmos a quantidade exata, mas termos uma noção para evitarmos pressão desnecessária no Garbage Collector. Quer entender com mais detalhes como isso funciona no GC? Confira aqui
Top comments (0)