11.9 集

包含不重复元素的集合称为“集(set)”。.NET Framework包含两个集(HashSet<T>和SortedSet<T>),它们都实现ISet<T>接口。HashSet<T>集包含不重复元素的无序列表,SortedSet<T>集包含不重复元素的有序列表。

ISet<T>接口提供的方法可以创建合集、交集,或者给出一个集是另一个集的超集或子集的信息。

在下面的示例代码中,创建了3个字符串类型的新集,并用一级方程式汽车填充它们。HashSet<T>集实现ICollection<T>接口。但是在该类中,Add()方法是显式实现的,还提供了另一个Add()方法。Add()方法的区别是返回类型,它返回一个布尔值,说明是否添加了元素。如果该元素已经在集中,就不添加它,并返回false(代码文件SetSample/Program.cs)。

        var companyTeams = new HashSet<string>()
        { "Ferrari", "McLaren", "Mercedes" };
        var traditionalTeams = new HashSet<string>() { "Ferrari", "McLaren" };
        var privateTeams = new HashSet<string>()
        { "Red Bull", "Toro Rosso", "Force India", "Sauber" };
        if (privateTeams.Add("Williams"))
        {
          WriteLine("Williams added");
        }
        if (! companyTeams.Add("McLaren"))
        {
          WriteLine("McLaren was already in this set");
        }

两个Add()方法的输出写到控制台上:

        Williams added
        McLaren was already in this set

IsSubsetOf()和IsSupersetOf()方法比较集和实现了IEnumerable<T>接口的集合,并返回一个布尔结果。这里,IsSubsetOf()方法验证traditionalTeams集合中的每个元素是否都包含在companyTeams集合方法中,IsSupersetOf()方法验证traditionalTeams集合是否有companyTeams集合没有的额外元素。

        if (traditionalTeams.IsSubsetOf(companyTeams))
        {
          WriteLine("traditionalTeams is subset of companyTeams");
        }
        if (companyTeams.IsSupersetOf(traditionalTeams))
        {
          WriteLine("companyTeams is a superset of traditionalTeams");
        }

这个验证的结果如下:

        traditionalTeams is a subset of companyTeams
        companyTeams is a superset of traditionalTeams

Williams也是一个传统队,因此这个队添加到traditionalTeams集合中:

        traditionalTeams.Add("Williams");
        if (privateTeams.Overlaps(traditionalTeams))
        {
          WriteLine("At least one team is the same with traditional and private teams");
        }

因为有一个重叠,所以结果如下:

        At least one team is the same with traditional and private teams.

调用UnionWith()方法,把引用新SortedSet<string>的变量allTeams填充为companyTeams、privateTeams和traditionalTeams的合集:

        var allTeams = new SortedSet<string>(companyTeams);
        allTeams.UnionWith(privateTeams);
        allTeams.UnionWith(traditionalTeams);
        WriteLine();
        WriteLine("all teams");
        foreach (var team in allTeams)
        {
          WriteLine(team);
        }

这里返回所有队,但每个队都只列出一次,因为集只包含唯一值。因为容器是SortedSet<string>,所以结果是有序的:

        Ferrari
        Force India
        Lotus
        McLaren
        Mercedes
        Red Bull
        Sauber
        Toro Rosso
        Williams

ExceptWith()方法从allTeams集中删除所有私有队:

        allTeams.ExceptWith(privateTeams);
        WriteLine();
        WriteLine("no private team left");
        foreach (var team in allTeams)
        {
          WriteLine(team);
        }

集合中的其他元素不包含私有队:

        Ferrari
        McLaren
        Mercedes