1. 概述
本章内容包括 .net平台中的集合、如何选择集合 以及 如何实现自定义集合。
2. 主要内容
2.1 使用数组(Array)
int[] arrayOfInt = new int[10];
for (int x = 0; x < arrayOfInt.Length; x++)
{
arrayOfInt[x] = x;
}
foreach (int i in arrayOfInt) //实现了IEnumerable
{
Console.Write(i); // Displays 0123456789
}
.net中还支持多维数组和锯齿(jagged)数组
string[,] array2D = new string[3, 2] { { “one”, “two” }, { “three”, “four” },
{ “five”, “six” } };
int[][] jaggedArray =
{
new int[] {1,3,5,7,9},
new int[] {0,2,4,6},
new int[] {42,21}
};
2.2 理解泛型和非泛型版本
*使用值类型作为泛型参数的时候,要注意可能会发生的装箱情况。比如值类型未实现IEquatable<T>或IComparable<T>的时候。
2.3 使用列表(List)
List<T>的定义:
public class List<T> : IList<T>, ICollection<T>, IList, ICollection,
IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
其中IList<T> 和 ICollection<T> 的定义如下:
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
{
T this[int index] { get; set; }
int IndexOf(T item);
void Insert(int index, T item);
void RemoveAt(int index);
}
public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
int Count { get; }
bool IsReadOnly { get; }
void Add(T item);
void Clear();
bool Contains(T item);
void CopyTo(T[] array, int arrayIndex);
bool Remove(T item);
}
下面是使用List<T>操作数据项的示例:
List<string> listOfStrings =
new List<string> { “A”, “B”, “C”, “D”, “E” };
for (int x = 0; x < listOfStrings.Count; x++)
Console.Write(listOfStrings[x]); // Displays: ABCDE
listOfStrings.Remove(“A”);
Console.WriteLine(listOfStrings[0]); // Displays: B
listOfStrings.Add(“F”);
Console.WriteLine(listOfStrings.Count); // Displays: 5
bool hasC = listOfStrings.Contains(“C”);
Console.WriteLine(hasC); // Displays: true
2.4 使用字典(Dictionary)
字典由键值对组成,可以根据键获取值。不允许重复的键。字典的定义:
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>,
ICollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection,
IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>,
IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, ISerializable,
IDeserializationCallback
字典的使用示例:
Person p1 = new Person { Id = 1, Name = “Name1” };
Person p2 = new Person { Id = 2, Name = “Name2” };
Person p3 = new Person { Id = 3, Name = “Name3” };
var dict = new Dictionary<int, Person>();
dict.Add(p1.Id, p1);
dict.Add(p2.Id, p2);
dict.Add(p3.Id, p3);
foreach (KeyValuePair<int, Person> v in dict)
{
Console.WriteLine(“{0}: {1}”, v.Key, v.Value.Name);
}
dict[0] = new Person { Id = 4, Name = “Name4” };
Person result;
if (!dict.TryGetValue(5, out result))
{
Console.WriteLine(“No person with a key of 5 can be found”);
}
2.5 使用集(sets)
sets是一个非重复的,无序集合。C#中set是系统保留关键字,可以使用HastSet<T>,它实现了ISet<T>。
public interface ISet<T> : ICollection<T>, IEnumerable<T>, IEnumerable
{
bool Add(T item);
void ExceptWith(IEnumerable<T> other);
void IntersectWith(IEnumerable<T> other);
bool IsProperSubsetOf(IEnumerable<T> other);
bool IsProperSupersetOf(IEnumerable<T> other);
bool IsSubsetOf(IEnumerable<T> other);
bool IsSupersetOf(IEnumerable<T> other);
bool Overlaps(IEnumerable<T> other);
bool SetEquals(IEnumerable<T> other);
void SymmetricExceptWith(IEnumerable<T> other);
void UnionWith(IEnumerable<T> other);
}
使用HashSet<T>的示例:
public void UseHashSet()
{
HashSet<int> oddSet = new HashSet<int>();
HashSet<int> evenSet = new HashSet<int>();
for (int x = 1; x <= 10; x++)
{
if (x % 2 == 0)
evenSet.Add(x);
else
oddSet.Add(x);
}
DisplaySet(oddSet);
DisplaySet(evenSet);
oddSet.UnionWith(evenSet);
DisplaySet(oddSet);
}
private void DisplaySet(HashSet<int> set)
{
Console.Write(“{“);
foreach (int i in set)
{
Console.Write(“ {0}”, i);
}
Console.WriteLine(“ }”);
}
2.6 使用队列(queue)和堆栈(stack)
队列主要用于临时存储数据,遵循先进先出的原则。三个重要的方法是:Enqueue、Dequeue、Peek。
Queue<string> myQueue = new Queue<string>();
myQueue.Enqueue(“Hello”);
myQueue.Enqueue(“World”);
myQueue.Enqueue(“From”);
myQueue.Enqueue(“A”);
myQueue.Enqueue(“Queue”);
foreach (string s in myQueue)
Console.Write(s + “ “);
// Displays: Hello World From A Queue
堆栈 遵循先进后出的原则。也具有跟队列类似的三个方法:Push、Pop、Peek。
Stack<string> myStack = new Stack<string>();
myStack.Push(“Hello”);
myStack.Push(“World”);
myStack.Push(“From”);
myStack.Push(“A”);
myStack.Push(“Queue”);
foreach (string s in myStack)
Console.Write(s + “ “);
// Displays: Queue A From World Hello
2.7 选择合适的集合
各个集合间最大的不同是 元素的访问方式:
① 列表和字典都支持元素的随机访问。字典提供了更快的元素读取速度,但是不能存储重复的数据项。
② 队列和堆栈提供了特定顺序的元素访问方式。元素取出后就自动从集合删除了。
③ 基于Set的集合,在元素比较方面有一些特性。但是不提供元素的随机访问。
2.8 创建自定义集合
.net提供的集合相关的接口包括: IEnumerable、IEnumerable<T>、IList<T>、ICollection<T>、IDictionary<TKey,TValue>、
ICollection<TKey,TValue>、ISet<T>。
也可以继承现有的集合对象来添加自定义的方法:
public class PeopleCollection : List<Person>
{
public void RemoveByAge(int age)
{
for (int index = this.Count - 1; index >= 0; index--)
{
if (this[index].Age == age)
{
this.RemoveAt(index);
}
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (Person p in this)
{
sb.AppendFormat(“{0} {1} is {2}”, p.FirstName, p.LastName, p.Age);
}
return sb.ToString();
}
}
3. 总结
① .net提供了泛型和非泛型的集合版本,使用的时候,优先选择泛型版本。
② 数组(Array)是最基础的集合,是定长的。
③ 列表(List)是使用最多的集合,是变长的。
④ 字典(Dictionary)是存取键值对的集合。
⑤ HashSet保存唯一项并提供相应的操作。
⑥ 队列是先进先出的集合。
⑦ 堆栈是先进后出的集合。
⑧ 可以通过实现指定的接口或者继承现有的集合来自定义集合类型。