C# -  Apresentando e usando HashSet<T> (.NET Core)


Hoje vamos tratar das coleções Set na .NET Core, focando na coleção HashSet<T>.

Uma coleção que contém apenas itens distintos é conhecida pelo conjunto de termos ou Set.

O .NET Core inclui dois conjuntos ou sets :  HashSet<T> e SortedSet<T>, que implementam a interface ISet<T>:

Ambas coleções armazenam itens não duplicados e estão presentes no namespace System.Collection.Generics.

No entanto, se você deseja desempenho e não se importa se os itens estão armazenados sem ordenação, utilize a coleção HashSet.

Por outro lado, se você quiser que os itens sejam ordenados após a inserção, mas não se importa tanto com o desempenho, utilize a coleção SortedSet.

A interface ISet<T> oferece métodos para criar uma união de múltiplos conjuntos, para criar uma interseção de conjuntos, ou para fornecer informações se um conjunto for um superconjunto ou subconjunto de outro.

Usando a coleção HashSet<T>

Vejamos um exemplo de utilização da coleção HashSet<T> que destaca o fato desta coleção não permitir itens duplicados. Assim vamos criar um array contendo um item duplicado e a seguir usar esse array para criar o HashSet<T> e veremos que o item duplicado não será adicionado na coleção.

Vamos criar um projeto .NET Core do tipo Console no VS 2017 Community e definir o código abaixo na classe Program.cs :

using System.Collections.Generic;
using static System.Console;
namespace EFCore_DeferredExecution
{
    class Program
    {
        static void Main(string[] args)
        {
            WriteLine("Usando HashSet");
            //1. definimos um array de strings (a string macoratti esta repetida) 
            string[] nomes = new string[] 
            {
                "macoratti","jefferson","jessica","macoratti","janice","miriam","marcia"
            };
            //2. Obtem o tamanho do array e imprime o array
            WriteLine($"Tamanho do Array : {nomes.Length}");
            WriteLine();
            WriteLine("Nomes no array");
            foreach (var n in nomes)
            {
                WriteLine(n);
            }

            WriteLine();
            //3. Definindo um HashSet que usa o array de strings
            HashSet<string> hSetNomes = new HashSet<string>(nomes);

            //4. Conta os elementos no HashSet
            WriteLine("No. de elementos no HashSet " + hSetNomes.Count);
            WriteLine();
            //5. Imprime os dados do HashSet (isto ira mostrar que não existe o nome duplicado) 
            WriteLine("Nomes no HashSet");
            foreach (var n in hSetNomes)
            {
                WriteLine(n);
            }
            ReadLine();
        }
    }
}

No código acima quando criamos o HashSet<T> :  

HashSet<string> hSetNomes = new HashSet<string>(nomes);

Veremos que como o HashSet<T> não suporta itens duplicados o nome duplicado não será incluído na coleção.

Abaixo temos o resultado obtido ao executar o projeto :

Comparando e Modificando um HashSets

Vamos agora realizar algumas operações com HashSet<T> usando os métodos :

No exemplo a seguir criamos quatros coleções HashSet<T> e a seguir usamos os métodos definidos acima. Ao final juntamos todas as coleções em uma coleção de itens ordenados usando SortedSet:

using System.Collections.Generic;
using static System.Console;
namespace NetCore_HashSet2
{
    class Program
    {
        static void Main(string[] args)
        {
            var timesSP = new HashSet<string>() { "Santos", "Palmeiras", "São Paulo" };
            var timesRJ = new HashSet<string>() { "Vasco", "Flamengo" };
            var timesBA = new HashSet<string>() { "Bahia", "Vitória" };
            var timesMundiais = new HashSet<string>() { "Santos", "Palmeiras", "São Paulo", "Flamengo" };
            if (timesSP.IsSubsetOf(timesMundiais))
            {
                WriteLine("timesSP é um subconjunto de timesMundiais\n");
            }
            if (timesMundiais.IsSupersetOf(timesSP))
            {
                WriteLine("timesMundiais é um superconjunto de timesRJ\n");
            }
            if (timesRJ.Overlaps(timesMundiais))
            {
                WriteLine("Pelo menos um time do RJ tem título Mundial");
            }
            WriteLine("\nJuntando dois HashSet<T> : SP e RJ\n");
            timesSP.UnionWith(timesRJ);
            foreach (var time in timesSP)
            {
                WriteLine(time);
            }
            var todosTimes = new SortedSet<string>(timesSP);
            todosTimes.UnionWith(timesRJ);
            todosTimes.UnionWith(timesBA);
            WriteLine();
            WriteLine("\n ### - Times de SP, RJ e BA  - ###\n");
            foreach (var time in todosTimes) 
            {
                WriteLine(time);
            }
            ReadLine();
        }
    }
}

Executando o projeto teremos o resultado a seguir:

A coleção HashSet<T> também possui o método SymmetricExceptWith que modifica o objeto HashSet<T> atual para conter apenas os elementos presentes nesse objeto ou na coleção especificada, mas não em ambos.

Veja um exemplo de sua utilização :

using System;
using System.Collections.Generic;
namespace NetCore_HashSet3
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] times1 = { "Santos", "Flamengo", "Grêmio" };
            string[] times2 = { "Santos", "Flamengo", "Palmeiras" };
            var hashTimes1 = new HashSet<string>(times1);

            hashTimes1.SymmetricExceptWith(times2);
            // Exibe os times
            foreach (var time in hashTimes1)
            {
                Console.WriteLine(time);
            }
            Console.ReadLine();
        }
    }
}

Neste código criamos dois arrays de strings e a seguir criamos um HashSet<T> como primeiro array.

Depois aplicamos o método SymmetricExceptWith ao segundo array de times. Neste momento o resultado final obtido vais conter apenas os times 'Grêmio' e 'Palmeiras' que não são comuns com ambos os arrays.

Temos o resultado exibido abaixo:



Concluindo podemos dizer que a coleção HashSet<T>  possui um ótimo desempenho, tendo também a vantagem de usar o objeto HashSet para executar operações como União, Interseção, etc., o que proporciona uma experiência de codificação fácil e sustentável.

Pegue o codigo do projeto aqui: NetCore_HashSet1.zip

"A luz semeia-se para o justo, e a alegria para os retos de coração."
Salmos 97:11

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

Referências:


José Carlos Macoratti