terça-feira, 10 de fevereiro de 2009

Artigo: Entendendo e Utilizando a Classe List

Vamos lá, neste artigo iremos falar da classe List presente no Generics apartir do .Net 3.5. Mas antes vamos dar uma passada rapida em estrutura de dados para termos noção de como a classe List é útil.

Qual a primeira forma que nos vem cabeça quando se fala em armazenar dados na memória?
Um vetor "arrays" seria a primeira resposta. Legal, mas se pararmos para pensar que um vetor é uma estrutura de dados estática. Isso nos deixa muito limitados, por exemplo.

Queremos armazenar um vetor com nomes de determinados alunos de uma sala de aula. Suponhamos que a sala tenha 20 alunos então teremos:

String [ ] nomeAlunos = new String [ 20 ];

No código acima nós criamos um array nomeAlunos do tipo que armazena variáveis do tipo string com 20 posições.

Mas, e se pararmos para pensar;
- Será que a sala de aula vai ter sempre 20 alunos?
- E se eu quiser remover um aluno?
- E se eu quiser adicionar um aluno?

Ai logo de cara você responde, tem sim como aumentar o tamanho do meu array e também tem como remover e adicionar um novo aluno!

Concordo com você, mais até o fim deste artigo você irá concordar comigo que usar a List é muito mais fácil e sem falar divertido.

Vamos lá, outro exemplo. suponhamos que o array nomeAlunos esteja assim.

nomeAlunos [ 0 ] = "Jose";
nomeAlunos [ 1 ] = "Joao";
nomeAlunos [ 2 ] = "Pedro";
nomeAlunos [ 3 ] = "Maria";
nomeAlunos [ 4 ] = "Helena";

Primeiro Problema: A Memória!
Nós temos um vetor de 20 posições e estamos utilizando somente 5 posições ou seja, temos 15 espaços alocados na memória atoa.

Segundo Problema: Deletar Aluno!
O João mudou de cidade, então tempos que deletar ele do nosso array. Deletando o João nosso array fica da seguinte forma:

nomeAlunos [ 0 ] = "José";
nomeAlunos [ 1 ] = ""; // espaço alocado atoa na memória
nomeAlunos [ 2 ] = "Pedro";
nomeAlunos [ 3 ] = "Maria";
nomeAlunos [ 4 ] = "Helena";

Caímos no Primeiro Problema, agora nos tempos 16 posições sendo alocadas na memória atoa.

Terceiro Problema: Adicionar novos alunos!
Logo de cara parece uma tarefa fácil, agora eu te pergunto: Em qual posição do array você vai adicionar o novo aluno?
Você logo me responde, adiciona na posição 1 para aproveitar o espaço alocado na memoria.
Correto, mas já imaginou o trabalho que você vai ter toda vez que precisar adicionar um novo elemento em um array, você vai ter que varrer todo o array em busca de um espaço livre.
Mas, e se eu adicionar em uma posição do array que já existe um aluno cadastrado?
O aluno cadastrado será sobreposto pelo novo aluno, você irá perder dados, e você não quer isso!

Quarto Problema: E se o array estiver lotado?
Você não pode simplesmente ir lá no array e mudar o tamanho do array para 22 posições. Pois ao fazer isso você estará criando um novo array de 22 posições e apagando todos os dados do array de 20.

Tem solução? Claro que tem, usando array:
Você copia os dados desse array de 20 para seu novo array de 22 posições. Concorda comigo que isso é um baita de um trabalho?

Você deve estar pensando, tudo tem solução usando no máximo uma estrutura de repetição, e pra que se preocupar com espaço vazio alocado na memoria já que hoje temos computadores com 4Gb de memoria.

É ai que está o X da questão, imagina se você precisar trazer centenas de dados de um Banco de Dados para trabalhar com eles durante o programar e depois ter que gravar esses dados novamente no Banco de Dados. Olha o trabalho que não vai ser gerenciar esse array. É ai que entra a classe List!


Agora vem a parte boa...

A classe List nada mais é que um vetor dinâmico. Vamos usar a classe List para o mesmo exemplo, olha que legal.

Vamos criar a List:

List<String>nomeAlunos = new List<String>();

No código assina nós criamos uma List nomeAlunos do tipo que armazena variáveis do tipo String. Notou alguma diferença? Eu não especifiquei o tamanho, pois como eu disse ela é dinâmica, aumenta ou diminui sua capacidade conforme a necessidade do programador.

Utilizando a Classe List você pode adicionar ou apagar um aluno em qualquer lugar da List sem perder dados. Legal né? Vamos a pratica!

Vamos adicionar os alunos na List: Isso é feito através do método Add como pode ser observado.

nomeAlunos.Add ( "Jose");
nomeAlunos.Add ( "Joao");
nomeAlunos.Add ( "Pedro");
nomeAlunos.Add ( "Maria");
nomeAlunos.Add ( "Helena");

Reparou algo de novo, nós não temos mais o indexador quando adicionamos um novo elemento na lista.

Por padrão a List vai adicionando novos elementos sempre no final. Portando o funcionamento é igual ao de um array sem a necessidade de informar o indexador.

O indexador só vai aparacer em casos específicos como quando você quiser buscar, adicionar ou imprimir algum elemento da List.

Olha só com a List fica indexada:

nomeAlunos[ 0 ] armazena "Jose"
nomeAlunos[ 1 ] armazena "Joao"
nomeAlunos[ 2 ] armazena "Pedro"
nomeAlunos[ 3 ] armazena "Maria"
nomeAlunos[ 4 ] armazena "Helena"

Pratica: Vamos aos mesmos problemas do Array?

Primeiro Problema: A Memória!
Não temos mais espaços alocados sem necessidades na memória. Então, não temos mais o problema da memória.

Segundo Problema: Deletar Aluno!
O Joao mudou de cidade, então tempos que deletar ele do nossa List. Facil, deletamos o João e a List anda com os outros dados para o lado do menor indexador. Assim ela nao deixa espaço alocado sem uso na memória.

Na pratica para deletar somento o Joao utilizamos o metodo RemoveAt e passamos como parâmetro o indexador 1 que é onde o Joao está armazenado.

nomeAlunos.RemoveAt ( 1 );

Depois de deletar Joao nossa List fica assim:

nomeAlunos[ 0 ] armazena "Jose"
nomeAlunos[ 1 ] armazena "Pedro"
nomeAlunos[ 2 ] armazena "Maria"
nomeAlunos[ 3 ] armazena "Helena"

Reparou o que aconteceu? Não tivemos espaços alocados sem necessidade na memória.


Terceiro Problema: Adicionar novos alunos!
Tarefa super fácil usando List:

Se você quiser apenas adicionar um novo aluno não é necessário especificar indexador, basta fazer o seguinte.

nomeAlunos.Add("Juca");

Facil né? Nossa List fica assim:

nomeAlunos[ 0 ] armazena "Jose"
nomeAlunos[ 1 ] armazena "Pedro"
nomeAlunos[ 2 ] armazena "Maria"
nomeAlunos[ 3 ] armazena "Helena"
nomeAlunos[ 4 ] armazena "Juca"


Tá bom, agora eu quero ver! Entrou um novo aluno, o Francisco. Mas eu quero adicionar na posição 3. Tem como?
Simples, fácil e rápido, quer ver?

nomeAlunos.Insert ( 3 , "Francisco" );

Utilizamos o método Insert, e nele passamos o indexador e o nome do Francisco. Não falei que era simples, facil e rapido?

E nossa lista fica assim:

nomeAlunos[ 0 ] armazena "Jose"
nomeAlunos[ 1 ] armazena "Pedro"
nomeAlunos[ 2 ] armazena "Maria"
nomeAlunos[ 3 ] armazena "Francisco"
nomeAlunos[ 4 ] armazena "Helena"
nomeAlunos[ 5 ] armazena "Juca"

Percebeu o que a List fez? Ela realocou os elementos acima e o 3 inclusive para uma posição posterior e adicionou Francisco na posição 3.

Quarto Problema: E se o List estiver lotado?
A List nunca vai estar lotado, e nunca vai alocar espaço na memoria atoa.


A grande jogada da List...

Até agora você sabe que a List é dinâmica. Mas essa não é a grande jogada da List já que essa é a função dela "ser dinâmica". A grande jogada está no conceito de Generics presente no .Net 3.5 como eu mencionei no inicio deste artigo.

O que vem a ser esse tal Generics?
O Generics permite que Classes, Métodos, Propriedades entre outras funcionalidades usem o tipo que você criou, ou seja, você não fica preso a tipos já programados como Int, String e Double.

E o que isso quer dizer?
Ficamos livres de boxing e unboxing, tá bom nem tando né, mais vai reduzir e muito as conversões.

Vamos a um exemplo prático!

Continuando com o mesmo exemplo da sala de aula. Só que agora nao queremos gravar somente o nome. Queremos gravar um tipo Aluno na List. Teremos:

public class Aluno {
                     public string Nome;
                public int Idade;
}                                

Criamos uma Classe Aluno com Métodos definindo as características dos alunos, viu como até agora não tem segredo nenhum!
Agora a única coisa que temos que fazer é criar um objeto da classe aluno, o resto é igual ao que foi explicado até aqui usando os Métodos da Classe List o Add, Insert e outros.

Vamos para pratica: Primeiro vamos criar nossa nova List

List<Aluno> listaAlunos = new List<Aluno> ( );

Percebeu diferença? Agora a List tem o tipo que você criou, ou seja ela é do tipo Aluno e vai armazena todas as características que você der para o Aluno.

E só para finalizar com a ultima pratica:

Aluno cadastraAluno = new Aluno ( );

Aqui nos criamos um Objeto que tem todas as características da Classe Aluno. Algum segredo em criar esse Objeto? Nada né, eu falei que ia ser divertido usar List.

cadastraAluno.Nome = "Luiz";

cadastraAluno.Idade = 8;

E novamente sem uso de Mágica ou algo do tipo atribuímos valores nas características do aluno. E por fim adicionamos o Objeto na List da mesmo jeito que você aprendeu.

listaAlunos.Add ( cadastraAluno );

Facil assim? Eu falei que era facil, rapido simples e divertido!

Bom, por hoje é só... Se tiverem alguma duvida deixe-as nos comentários.



Ah, já estava esquecendo... Apartir de hoje você ainda vai usar array?


11 comentários:

  1. Muito bom o artigo, fácil e acessível.
    Parabéns.
    Estava com dificuldade de usar o list<>, mas depois que achei esse artigo não tive mais problemas.
    vlw
    ;)

    ResponderExcluir
  2. Muito bom o artigo. Agora a duvida é como leio os valores dentro da List. Se quiser por exemplo no caso da classe aluno jogar o nome e a idade em textbox?

    ResponderExcluir
  3. Como irei imprimir os dados dentro das classes que estão no list?

    ResponderExcluir
  4. Como ficaria para imprimir todos os elementos de uma classe dentro de uma List???

    ResponderExcluir
  5. Cara entendi tudo...
    Muito bom esses comentários mesmo
    huhuuuuu
    array ja era hahahhaha

    ResponderExcluir
  6. Oi,

    Muito explicativo e didático seu post.

    Obrigada,

    Mariana

    ResponderExcluir
  7. Quando se usa o método do Insert da lista, a lista se reorganiza ou sobreescreve o valor (no seu caso o nome da posição 3)?

    ResponderExcluir
  8. Ótima a sua explicação! Parabéns

    ResponderExcluir
  9. Muito legal! Se todo professor ensinasse assim seria fácil aprender Programação.Parabéns!

    ResponderExcluir
  10. Muito obrigado... finalmente entendi o conceito de ... xD Repondendo sua pergunta "adeus array" kkkkkkkk

    ResponderExcluir
  11. Muito bom mesmo! Adorei o artigo, leve, esclarecedor e direto! Entendi perfeitamente o conceito. Muito obrigado e parabéns!

    ResponderExcluir