Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Универсальные коллекции языка С#. Учебное пособие
.pdf
}
else
{
if(x.Pop==y.Pop)return0;
elsereturn1;
}
}
publicintCompareTo(Cityx)
{
//СравнениеобъектовCity.
returnCompare(this,x);
}
publicoverrideboolEquals(objectobj)
{
if(this==null&obj==null)returntrue;
else
return(objasCity).CompareTo(this)==0;
}
}
staticvoidMain(string[]args)
{
City[]towns=
{
newCity("Москва",12678),
newCity("Санкт‐Петербург",5398),
newCity("Новосибирск",1625),
new
newCity("НижнийНовгород",1252),
newCity("Казань",1257),
newCity("Челябинск",1196),
newCity("Омск",1154)
};
LinkedList<City>cities=newLinkedList<City>(towns);
Console.WriteLine("Исходныйсписок:");
foreach(varelincities)Console.WriteLine(el);
IEnumerable<City>cur=cities.OrderBy(x=>x.Name);
Console.WriteLine("Список сортированный по полю Nameвпорядке
возрастания:");
foreach(var
if(this!=null&obj==null|this==null&obj!=null)returnfalse;
City("Екатеринбург",1493),
elincur)Console.WriteLine(el);
61

cur=cities.OrderByDescending(x=>x.Pop);
Console.WriteLine("СписоксортированныйпополюPopвпорядкеубывания:");
foreach(varelincur)Console.WriteLine(el);
intsum=cities.Sum(x=>x.Pop);
Console.WriteLine($"Суммарная численность населения в городах списка =
{sum}");
}
}
}
Результатработыпримера:
Исходныйсписок:
Москва,12678
Санкт‐Петербург,5398
Новосибирск,1625
Екатеринбург,1493
НижнийНовгород,1252
Казань,1257
Челябинск,1196
Омск,1154
СписоксортированныйпополюNameвпорядкевозрастания:
Екатеринбург,1493
Казань,1257
Москва,12678
НижнийНовгород,1252
Новосибирск,1625
Омск,1154
Санкт‐Петербург,5398
Челябинск,1196
СписоксортированныйпополюPopвпорядкеубывания:
Москва,12678
Санкт‐Петербург,5398
Новосибирск,1625
Екатеринбург,1493
Казань,1257
НижнийНовгород,1252
Челябинск,1196
Омск,1154
Суммарнаячисленностьнаселениявгородахсписка=26053
62

УНИВЕРСАЛЬНЫЕ МНОЖЕСТВА –
КОЛЛЕКЦИИ HASHSET<T> И SORTEDSET<T>
Коллекция, содержащая только отличающиеся элементы, называется множеством (set). В составе С# имеются два множества:
HashSet<T> и SortedSet<T>. Оба они реализуют интерфейс ISet<T>.
Коллекция HashSet<T> содержит неупорядоченное множество различающихся элементов, а в SortedSet<T> элементы упорядочены.
Интерфейс ISet<T> (см. Интерфейсы) предоставляет методы для
создания объединения нескольких множеств, пересечения множеств
и определения, является ли
одно множество надмножеством или подмножеством другого. В следующей таблице перечислены операции
и их математические эквиваленты.
Операция Математический эквивалент
UnionWith Объединение наборов
IntersectWith Пересечение наборов
ExceptWith Вычитание наборов
SymmetricExceptWith Симметричное различие (включает элементы, принад-
лежащие только одному и только второму набору)
Помимо перечисленных операций над наборами класс HashSet<T>
и SortedSet<T> предоставляет также методы для определения равенства наборов, перекрытия наборов и того, является ли набор подмножеством или надмножеством другого набора.
КОЛЛЕКЦИЯ HASHSET<T> – НЕУПОРЯДОЧЕННОЕ МНОЖЕСТВО
Объект класса HashSet<T> представляет неупорядоченное множество значений типа Т. Здесь Т – тип элементов в коллекции. Класс
HashSet<T> реализует следующие интерфейсы:
ICollection<T>, IEnumerable<T>, IReadOnlyCollection<T>, IEnumerable, ISet<T>, IDeserializationCallback, ISerializable.
Объекты класса HashSet<T> обеспечивают высокопроизводительные операции с наборами. Набор – это коллекция, не содержащая повторяющихся элементов, элементы которой не имеют определенного
порядка.
63

Ниже перечислены наиболее употребляемые конструкторы класса
HashSet<T>:
publicHashSet()
publicHashSet(IEnumerable<T>collection)
publicHashSet(IEqualityComparecomparer)
publicHashSet(IEnumerable<T>collection,IEqualityComparecomparer)
В первой форме конструктора создается пустое множество, а во
второй форме – множество, состоящее из элементов указываемой коллекции collection. В третьей форме конструктора допускается указывать способ сравнения с помощью параметра comparer. В четвертой
форме создается множество, состоящее из элементов указываемой
коллекции collection, и используется заданный способ сравнения
comparer.
В этом классе предоставляется также
метод RemoveWhere(), уда-
ляющий из множества элементы, удовлетворяющие заданному условию или предикату. Помимо свойств, определенных в интерфейсах,
которые реализуются в классе HashSet<T>, в него введено дополнительное свойство Comparer, приведенное ниже:
publicIEqualityComparer<T>Comparer{get;}
Оно позволяет получать метод сравнения вызывающего хеш-множества.
В следующем примере показано, как объединить два разнородных
набора значений типа int. В примере создается два объекта
evenNumbers, oddNumbers класса HashSet<T> и заполняются четными
и нечетными числами соответственно. Третий объект numbers типа
HashSet<T> создается из набора, содержащего четные числа. Затем
с помощью метода UnionWith к numbers добавляется oddNumbers.
usingSystem;
usingSystem.Collections.Generic;
namespaceExample_1
{
classProgram
{
staticvoidMain(string[]args)
{
64

HashSet<int>evenNumbers=newHashSet<int>();
HashSet<int>oddNumbers=newHashSet<int>();
for(inti=0;i<5;i++)
{
//Заполняеммножествотолькочетнымичислами.
evenNumbers.Add(i*2);
//Заполняеммножествотольконечетнымичислами.
oddNumbers.Add((i*2)+1);
}
Console.Write($"evenNumbersсодержит{evenNumbers.Count}элементов:");
DisplaySet(evenNumbers);
Console.Write($"oddNumbersсодержит{oddNumbers.Count}элементов:");
DisplaySet(oddNumbers);
//СоздаемновыйHashSetзаполненныечетнымичислами.
HashSet<int>numbers=newHashSet<int>(evenNumbers);
Console.WriteLine("numbersобъединяемсoddNumbers...");
numbers.UnionWith(oddNumbers);
Console.Write($"numbersсодержит{numbers.Count}элементов:");
DisplaySet(numbers);
}
staticvoidDisplaySet(HashSet<int>collection)
{
Console.Write("{");
foreach(intiincollection)
{
Console.Write($"{i}");
}
Console.WriteLine("}");
}
}
}
Результатработыпримера:
evenNumbersсодержит5элементов:{
oddNumbersсодержит5элементов:{13579}
numbersобъединяемсoddNumbers...
numbersсодержит10элементов:{0246813579}
02468}
В следующем примере показано, как работать с множеством
HashSet<T> объектов класса Box. Создаются два объекта HashSet<Box>
c разными функциями для сравнения и хэширования объектов
класса Box. Они описаны в двух классах BoxEqualityComparer
65

и BoxEquality Comparer1, реализующих интерфейс IEqualityComparer
<Box>. В коллекцию добавляются объекты методом Add и удаляются
методом RemoveWhere по условию, заданному лямбда-выражением (см.
раздел Лямбда-выржения), затем элементы коллекции выводятся на
консоль. Попытка добавления дублирующего элемента игнорируется.
publicclassBox
{
publicBox(inth,intl,intw)
{
this.Height=h;//Высрта.
this.Length=l;//Длина.
this.Width=w;//Ширина.
}
publicintHeight{get;set;}
publicintLength{get;set;}
publicintWidth{get;set;}
publicintVolume{get{returnHeight*Length*Width;}}
publicoverrideStringToString()
{
returnString.Format($"({Height},{Length},{Width})");
}
}
//Класс,реализующийфункциюEqualsинтерфейсаIEqualityComparer,
//обеспечивающуюпроверкуобъектовBoxнаравенство.
classBoxEqualityComparer1:IEqualityComparer<Box>
{
publicboolEquals(Boxb1,Boxb2)
{
if(b2==null&&b1==null)
returntrue;
elseif(b1==null||b2==null)
returnfalse;
elseif(b1.Volume==b2.Volume)
returntrue;
else
returnfalse;
}
//Хэш‐функциядляпомещенияобъектавHashSet.
publicintGetHashCode(Boxbx)
{
inthCode=bx.Volume;
66

returnhCode.GetHashCode();
}
}
//Класс,реализующийфункциюEqualsинтерфейсаIEqualityComparer,
//обеспечивающуюпроверкуобъектовBoxнаравенство.
classBoxEqualityComparer:IEqualityComparer<Box>
{
publicboolEquals(Boxb1,Boxb2)
{
if(b2==null&&b1==null)
returntrue;
elseif(b1==null||b2==null)
returnfalse;
elseif(b1.Height==b2.Height&&b1.Length==b2.Length
&&b1.Width==b2.Width)
returntrue;
else
returnfalse;
}
//Хэш‐функциядляпомещенияобъектавHashSet.
publicintGetHashCode(Boxbx)
{
inthCode=bx.Height^bx.Length^bx.Width;;
returnhCode.GetHashCode();
}
}
usingSystem;
usingSystem.Collections.Generic;
namespaceExample_2
{
classProgram
{
staticvoidMain(string[]args)
{
HashSet<Box>boxes=newHashSet<Box>(newBoxEqualityComparer())
{
newBox(1,2,3),
newBox(2,4,3),
newBox(5,2,6),
};
67

boxes.Add(newBox(4,2,7));
boxes.Add(newBox(1,1,6));
Display(boxes);
intc=boxes.RemoveWhere(b=>b.Volume<30);
Console.WriteLine($"Удалено‐{c}элементов.");
Display(boxes);
varbox=newHashSet<Box>(boxes,newBoxEqualityComparer1());
if(!box.Add(newBox(2,5,6)))
Console.WriteLine($"ЭлементстакимзначниемVolumeвомножествеесть.");
Display(box);
}
staticvoidDisplay(IEnumerable<Box>x)
{
Console.Write("{");
foreach(varel
Console.Write(el.ToString());
Console.WriteLine("}");
}
}
}
Результатработыпримера:
{(1,2,3)(2,4,3)(5,2,6)(4,2,7)(1,1,6)}
Удалено‐3элементов.
{(5,2,6)(4,2,7)}
ЭлементстакимзначениемVolumeвомножествеесть.
{(5,2,6)(4,2,7)}
inx)
УПОРЯДОЧЕННОЕ МНОЖЕСТВО – КЛАСС SORTEDSET<T>
Коллекция SortedSet<T> представляет упорядоченное множество.
Здесь T – тип объектов коллекции. Объект класса SortedSet<T> поддерживает коллекцию в сортированном порядке. Дублирующиеся элементы в коллекции не допускаются. Изменение значений элементов
коллекции не поддерживается.
Ниже перечислены четыре наиболее часто используемых конструктора, определенных в классе SortedSet<T>:
publicSortedSet()
publicSortedSet(IEnumerable<T>collection)
publicSortedSet(IComparercomparer)
publicSortedSet(IEnumerable<T>collection,IComparercomparer)
68

В первой форме конструктора создается пустое множество, а во
второй форме – множество, состоящее из элементов указываемой коллекции collection. В третьей форме конструктора допускается указывать способ сравнения с помощью параметра comparer. В четвертой
форме создается множество, состоящее из элементов указываемой
коллекции collection, и используется заданный способ сравнения
comparer.
Упорядоченное множество предоставляет метод GetViewBetween(),
возвращающий часть множества как объект типа SortedSet<T>, метод
RemoveWhere(), удаляющий из множества элементы, удовлетворяющие
заданному условию, или предикату (см. раздел Делегат Predicate),
а также метод Reverse(), возвращающий объект типа IEnumerable<T>,
который позволяет циклически получить доступ к элементам множества в обратном порядке.
Помимо свойств, определенных в интерфейсах (см. раздел Интерфейсы), которые реализуются в
дополнительные свойства, приведенные ниже:
publicIComparer<T>Comparer{get;}
publicTMax{get;}
publicTMin{get;}
классе SortedSet<T>, в нем имеются
Свойство Comparer обеспечивает доступ к способу сравнения
для вызывающего множества. Свойство Мах обеспечивает доступ
к наибольшему значению во множестве, а свойство Min – к наименьшему значению во множестве.
В следующем примере создается и инициализируется объект set
класса SortedSet<T> с помощью конструктора без параметров. При создании set инициализируется тремя объектами класса Record, затем
в него добавляются
два объекта с помощью метода Add и элементы
множества выводятся на консоль. Затем предпринимается попытка добавить в множество имеющийся элемент. Выводится число элементов,
минимальный и максимальный элементы множества. С помощью
функции Reverse элементы множества просматриваются в обратном
порядке. С помощью функции Count и лямбда-выражения (см. раздел
Лямбда-выражения) подсчитывается число элементов со
свойством,
заданным лямбда-выражением. С помощью функции TakeWhile и
лямбда-выражения выводятся на консоль элементы со свойством, заданным лямбда-выражением.
69

Класс Record содержит два автоматически распределяемых свойства типа double и реализует интерфейсы IComparable<Record>,
IComparer<Record>, которые обеспечивают компараторы для сравнения на равенство и упорядочения объектов. В нем переопределен метод ToString().
publicclassRecord:IComparable<Record>,IComparer<Record>
{
publicdoublere{get;}
publicdoubleim{get;}
publicRecord(doubler,doublei)
{
re=r;im=i;
}
publicdoubleModule()
{
returnMath.Sqrt(re*re+im*im);
}
//СравнениеобъектовRecord.
publicintCompare(Recordx,Recordy)
{
if(x.Module()<y.Module())
{
return‐1;
}
else
{
if(x.Module()==y.Module())return0;
elsereturn1;
}
}
//СравнениеобъектовRecord.
publicintCompareTo(Recordx)
{
returnCompare(this,x);
}
publicoverridestringToString()
{
return$"({re.ToString()},{im.ToString()})";
}
}
70
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
