Опубликован: 19.02.2009 | Доступ: свободный | Студентов: 3059 / 791 | Оценка: 4.35 / 4.11 | Длительность: 16:28:00
ISBN: 978-5-94774-401-9
Лекция 16:

Коллекции

Рассмотрим несколько примеров использования динамического массива.

using System;
using System.Collections;

namespace MyProgram
{
 class Program
 {
  static void ArrayPrint(string s, ArrayList a)
  {
   Console.WriteLine(s);
   foreach (int i in a)
    Console.Write(i + " ");
   Console.WriteLine();
  }

  static void Main(string[] args)
  {
   ArrayList myArray = new ArrayList();
   Console.WriteLine("Начальная емкость массива: " + myArray.Capacity);
   Console.WriteLine("Начальное количество элементов: " + myArray.Count);

   Console.WriteLine("\nДобавили 5 цифр");
   for (int i = 0; i < 5; i++) myArray.Add(i);
   Console.WriteLine("Текущая емкость массива: " + myArray.Capacity);
   Console.WriteLine("Текущее количество элементов: " + myArray.Count);
   ArrayPrint("Содержимое массива", myArray);
      
   Console.WriteLine("\nОптимизируем емкость массива");
   myArray.Capacity=myArray.Count;
   Console.WriteLine("Текущая емкость массива: " + myArray.Capacity);
   Console.WriteLine("Текущее количество элементов: " + myArray.Count);
   ArrayPrint("Содержимое массива", myArray);

   Console.WriteLine("\nДобавляем элементы в массив");
   myArray.Add(10);
   myArray.Insert(1, 0); 
   myArray.AddRange(myArray);
   Console.WriteLine("Текущая емкость массива: " + myArray.Capacity);
   Console.WriteLine("Текущее количество элементов: " + myArray.Count);
   ArrayPrint("Содержимое массива", myArray);

   Console.WriteLine("\nУдаляем элементы из массива");
   myArray.Remove(0);
   myArray.RemoveAt(10);
   Console.WriteLine("Текущая емкость массива: " + myArray.Capacity);
   Console.WriteLine("Текущее количество элементов: " + myArray.Count);
   ArrayPrint("Содержимое массива", myArray);

   Console.WriteLine("\nУдаляем весь массив");
   myArray.Clear();
   Console.WriteLine("Текущая емкость массива: " + myArray.Capacity);
   Console.WriteLine("Текущее количество элементов: " + myArray.Count);
   ArrayPrint("Содержимое массива", myArray);
  }
 }
}

Пример 2.В текстовом файле записана информация о людях (фамилия, имя, отчество, возраст, вес через пробел). Вывести на экран информацию о людях, отсортированную по возрасту.

using System;
using System.Collections;
using System.IO;
using System.Text;

namespace MyProgram
{
 class Program
 {
  public struct one //структура для хранения данных об одном человеке
  {
   public string f;
   public string i;
   public string o;
   public int age;
   public float massa;
  }

  public class SortByAge : IComparer //реализация стандартного интерфейса 
  {
   int IComparer.Compare(object x, object y)  //переопределение метода Compare
   {
    one t1 = (one)x;
    one t2 = (one)y;
    if (t1.age > t2.age) return 1;
    if (t1.age < t2.age) return -1;
    return 0;
   }
  }

  static void ArrayPrint(string s, ArrayList a)
  {
   Console.WriteLine(s);
   foreach (one x in a)
    Console.WriteLine(x.f + "\t"+ x.i + "\t"+ x.o + "\t"+x.age + "\t" + x.massa);
  }

  static void Main(string[] args)
  {
    StreamReader fileIn = new StreamReader("t.txt",Encoding.GetEncoding(1251));
    string line;
    one a;
    ArrayList people = new ArrayList();
    string[] temp = new string[5];
    while ((line=fileIn.ReadLine())!=null) //цикл для организации обработки файла 
    {
     temp = line.Split(' '); 
     a.f = temp[0];
     a.i = temp[1];
     a.o = temp[2];
     a.age = int.Parse(temp[3]);
     a.massa = float.Parse(temp[4]);
     people.Add(a);
    }
    fileIn.Close();

    ArrayPrint("Исходные данные: ", people);
    people.Sort(new Program.SortByAge());  //вызов сортировки
    ArrayPrint("Отсортированные данные: ", people);
  }
 }
}
______________t.txt________________
Иванов Сергей Николаевич 21 64
Петров Игорь Юрьевич 45 88
Семёнов Михаил Алексеевич 20 70
Пиманов Александр Дмитриевич 53 101
Замечание. Обратите внимание на то, что в данном примере был разработан вложенный класс SortByAge, реализующий стандартный интерфейс IComparer. В этом классе был перегружен метод Compare, позволяющий сравнивать между собой два объекта типа one. Созданный класс использовался для сортировки коллекции по заданному критерию (по возрасту).
Класс Hashtable

Класс Hashtable предназначен для создания коллекции, в которой для хранения объектов используется хеш-таблица. В хеш-таблице для хранения информации используется механизм, именуемый хешированием (hashing). Суть хеширования состоит в том, что для определения уникального значения, которое называется хеш-кодом, используется информационное содержимое соответствующего ему ключа. Хеш-код затем используется в качестве индекса, по которому в таблице отыскиваются данные, соответствующие этому ключу. Преобразование ключа в хеш-код выполняется автоматически, т.е. сам хеш-код вы даже не увидите. Но преимущество хеширования - в том, что оно позволяет сокращать время выполнения таких операций, как поиск, считывание и запись данных, даже для больших объемов информации.

Класс Hashtable реализует стандартные интерфейсы IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback и ICloneable. Размер хеш-таблицы может динамически изменяться. Размер таблицы увеличивается тогда, когда количество элементов превышает значение, равное произведению вместимости таблицы и ее коэффициента заполнения, который может принимать значение на интервале от 0,1 до 1,0. По умолчанию установлен коэффициент равный 1,0.

В классе Hashtable определено несколько конструкторов:

public Hashtable()   //создает пустую хеш-таблицу 
// строит хеш-таблицу, которая инициализируется элементами коллекции с
public Hashtable(IDictionary с) 
public Hashtable(int capacity) //создает хеш-таблицу с вместимостью capacity
//создает хеш-таблицу вместимостью capacity и коэффициентом заполнения n 
public Hashtable(int capacity, float n)

Помимо методов, определенных в интерфейсах, которые реализует класс Hashtable, в нем определены и собственные методы:

Метод Описание
public virtual bool ContainsKey (object k) Возвращает значение true , если в вызывающей хеш-таблице содержится ключ, заданный параметром k. В противном случае возвращает значение false
public virtual bool ContainsValue (object v) Возвращает значение true, если в вызывающей хеш-таблице содержится значение, заданное параметром v. В противном случае возвращает значение false
public virtual IDictionaryEnumerator GetEnumerator() Возвращает для вызывающей хеш-таблицы нумератор типа IDictionaryEnumerator

В классе Hashtable, помимо свойств, определенных в реализованных им интерфейсах, определены два собственных public -свойства:

public virtual ICollection Keys { get; } //позволяет получить коллекцию ключей
public virtual ICollection Values { get; } //позволяет получить коллекцию значений

Для добавления элемента в хеш-таблицу необходимо вызвать метод Add(), который принимает два отдельных аргумента: ключ и значение. Важно отметить, что хеш-таблица не гарантирует сохранения порядка элементов, т.к хеширование обычно не применяется к отсортированным таблицам.

Рассмотрим пример, который демонстрирует использование Hashtable коллекции:

Пример 1:рассмотрим простые операции с хеш-таблицей

using System;
using System.Collections;

namespace MyProgram
{
 class Program
 {
    
  static void printTab(string s, Hashtable a)
  {
   Console.WriteLine(s);
   ICollection key = a.Keys; //Прочитали все ключи
   foreach (string i in key)//использование ключа для получения значения
   {
    Console.WriteLine(i+"\t"+a[i]);
   }
   Console.WriteLine();
  }

  static void Main(string[] args)
  {
   Hashtable tab = new Hashtable();
   Console.WriteLine("Начальное количество элементов: " + tab.Count);
   printTab("Содержимое таблицы: ", tab);

   Console.WriteLine("Добавили в таблицу записи");
   tab.Add("001","ПЕРВЫЙ");
   tab.Add("002","ВТОРОЙ");
   tab.Add("003","ТРЕТИЙ");
   tab.Add("004", "ЧЕТВЕРТЫЙ");
   tab.Add("005", "ПЯТЫЙ");
   Console.WriteLine("Текущее количество элементов: " + tab.Count);
   printTab("Содержимое заполненной таблицы", tab);
   tab["005"] = "НОВЫЙ ПЯТЫЙ";
   tab["001"] = "НОВЫЙ ПЕРВЫЙ";
   printTab("Содержимое измененной таблицы", tab); 
  }
 }
}

Пример 2. Разработаем простейшую записную книжку, в которую можно добавлять и удалять телефоны, а также осуществлять поиск номера телефона по фамилии и фамилии по номеру телефона.

using System;
using System.Collections;
using System.IO;
using System.Text;

namespace MyProgram
{
 class Program
 {
  static void printTab(string s, Hashtable a)
  {
   Console.WriteLine(s);
   ICollection key = a.Keys; //Прочитали все ключи
   foreach (string i in key)//использование ключа для получения значения
   {
    Console.WriteLine(i + "\t" + a[i]);
   }
  }

  static void Main(string[] args)
  {
    StreamReader fileIn = new StreamReader("t.txt",Encoding.GetEncoding(1251));
    string line;
    Hashtable people = new Hashtable();
    while ((line = fileIn.ReadLine()) != null) //цикл для организации обработки файла 
    {
     string [] temp = line.Split(' ');
     people.Add(temp[0],temp[1]);
    }
    fileIn.Close();
    printTab("Исходные данные: ", people);
    
    Console.WriteLine("Введите номер телефона");
    line = Console.ReadLine();
    if (people.ContainsKey(line)) Console.WriteLine(line + "\t" + people[line]);
    else
    {
     Console.WriteLine("Такого номера нет в записной книжке.\nВведите фамилию: ");
     string line2=Console.ReadLine();
     people.Add(line,line2);
    }
    printTab("Исходные данные: ", people);

    Console.WriteLine("Введите фамилию для удаления");
    line = Console.ReadLine();
    if (people.ContainsValue(line))
    {
     ICollection key =people.Keys; //Прочитали все ключи
     Console.WriteLine(line);
     string del="";
     foreach (string i in key)//использование ключа для получения значения
      if (string.Compare((string)people[i], line) == 0)
      {
       del = i;
       break;
      }

     Console.WriteLine(del + "\t" + people[del] + "- данные удалены!!!");
     people.Remove(del);
     printTab("Измененные данные: ", people);       
    }
    else Console.WriteLine("Такого абонента в записной книжке нет ");
  }
 }
}
_________t.txt____________
12-34-56 Иванов
78-90-12 Петров
34-56-78 Семёнов
90-11-12 Пиманов