150 likes | 389 Views
Лекция 6. Ассоциативные коллекции. Отличие от последовательных. В последовательной коллекции каждый элемент ассоциируется с номером, начиная с 0. В ассоциативной коллекции элементы идентифицируются уникальными ключами произвольного типа – числа, строки, пользовательские классы, …
E N D
Лекция 6 Ассоциативные коллекции
Отличие от последовательных В последовательной коллекции каждый элемент ассоциируется с номером, начиная с 0. В ассоциативной коллекции элементы идентифицируются уникальными ключами произвольного типа – числа, строки, пользовательские классы, … Но у всех коллекций есть нечто общее, и это общее – интерфейсы.
Интерфейсы коллекций GetEnumerator() Count this[int] Add(), Remove()…
Интерфейс IDictionary publicstructKeyValuePair<TKey, TValue> { publicKeyValuePair(TKey key, TValue value); publicTKey Key { get; } publicTValue Value { get; } publicoverridestringToString(); } publicinterfaceIDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>> { ICollection<TKey> Keys { get; } ICollection<TValue> Values { get; } TValuethis[TKey key] { get; set; } void Add(TKey key, TValue value); boolContainsKey(TKey key); bool Remove(TKey key); boolTryGetValue(TKey key, outTValue value); } K V K V K V K V
Классы ассоциативных коллекций • HashTable • Dictionary<TKey, TValue> • SortedDictionary<TKey, TValue>
Хэш-таблица Запись Хешируем ключ и получаем адрес. Если адрес свободен, записываем. Если занят, рехешируем ключ. goto 2. Чтение Хешируем ключ и получаем адрес. Если адрес свободен, значения нет. Если занят, сверяем ключи Если ключи совпали, читаем Если не совпали, рехешируем ключ. goto 2
Хэш-таблица Удаление Определяем адрес, как для чтения. Помечаем ключ как удаленный.
Пример: Частотный словарь Задан текст (массив слов). Составить для него частотный словарь. privatestaticDictionary<string, int> CreateDictionary(string[] words) { Dictionary<string, int> dict = newDictionary<string, int>(); foreach (string word in words) { if (dict.ContainsKey(word)) dict[word]++; else dict[word] = 1; } returndict; }
Эквивалентность в .NET Объекты, которые служат ключами в ассоциативных коллекциях, должны допускать операцию проверки эквивалентности. Строки, числа, символы допускают проверку эквивалентности. В пользовательских объектах операцию эквивалентности необходимо объявлять.
Метод Object.Equals() В классе Object есть виртуальный метод bool Equals(object o), он считает объект эквивалентным только самому себе. Если программиста не устраивает такая семантика, он должен перекрыть этот метод в своем классе. Например, для класса Point это может быть сделано так. publicoverridebool Equals(Object obj) { // Если параметр равен null, возвращаем false. if (obj == null) returnfalse; // Если параметр не приводится к Point, возвращаем false. Point p = objas Point; if ((System.Object)p == null)// антицикл returnfalse; // Возвращаем true, если поля равны. return (x == p.x) && (y == p.y); } Замечание. Закрытые поляp.x,p.yвидны так же, как иthis.x,this.y.
Равна ли точка цветной точке? classPoint { publicint X, Y; } classColPoint: Point { publicColor C; } Эквивалентными считаются только однотипные объекты. В противном случае ожидаются парадоксы, т.е. из A == B и B == Cбудет следовать, что A == C . • Свойства эквивалентности: • Рефлексивность • Симметричность • Транзитивность
Эквивалентность в .NET Кроме метода Equals(), в классе Object есть еще два статических метода: publicstaticboolReferenceEquals(objectobjA, objectobjB); publicstaticbool Equals(objectobjA, objectobjB); и метод publicvirtualintGetHashCode(); Порядок определения пользовательской эквивалентности: перекрываем метод экземпляра Equals(); перекрываем метод экземпляра GetHashCode(); остальные методы не трогаем.
Операции == и!= Вместе с перегрузкой метода Equals() нужно пергружать не только GetHashCode(), но и операции сравнения.
Самостоятельно Разработайте класс «Телефонный справочник», который бы мог хранить произвольное количество абонентов. Для каждого абонента известна фамилия и один номер телефона. Фамилии разных абонентов могут быть одинаковыми, номера телефонов – нет. Справочник должен выполнять поиск номеров телефонов по фамилии и поиск фамилии по номеру телефона Сделайте класс Point способным выполнить роль ключа в ассоциативной коллекции. Унаследуйте List<T> и добавьте в наследник проверку эквивалентности. Коллекции считаются эквивалентными, если состоят из попарно эквивалентных элементов.