集合
本文主要介绍如何使用对象组,讨论数组列表、字典和集合,以及如何在C#代码中正确使用它们,以获得最佳性能。
一、对象组
在.NET基类中,最简单的数据结构是数组,它是System.Array类的一个实例,数组的有点是可以高效的访问给定下标的元素,使用数组编程比较直观;缺点是实例化时必须指定数组的大小,且不能添加、插入或删除元素。另外数组还必须给定下标 才能访问其中的元素,但在对数组元素进行遍历的时候,这个下标并不是很有用。
.NET扩展了对许多在不同环境下使用的其他数据结构的支持,不仅如此,.NET还有许多接口,类实现这些接口后,就可以声明它们支持某种数据结构类型的全部功能。下面介绍3个这样的结构:(下面几种结构类都在System.Collections命名空间中)
1、数组列表
2、集合
3、字典
1.1 数组列表(System.Collections.ArrayList)
ArrayList和StringBuilder相似,其容量可以自动增长。即初始化的时候可以指定其容量(默认值是16),当添加的对象数超出其容量的时候,ArrayList的容量就会自动增大,新增的内存区域可以是成倍增长。
下面是ArrayList的一些基本功能:
1.2 集合
集合表示一组可以通过遍历每个元素来访问的一组对象,特别是可以使用foreach循环来访问它们。使用foreach循环是集合的主要目的,并无其它特性。
集合要能使用foreach循环,必须实现System.Collections.IEnumerable接口
1.3 字典
字典还可以称为映射或散列表,这种数据结构允许按照某个键来访问元素,键可以是任意数据类型,也可以向字典任意添加和删除元素。
在.NET中基本的字典是由HashTable类来表示的,其键和条目都是object类型。其基本用法如下:
一、对象组
在.NET基类中,最简单的数据结构是数组,它是System.Array类的一个实例,数组的有点是可以高效的访问给定下标的元素,使用数组编程比较直观;缺点是实例化时必须指定数组的大小,且不能添加、插入或删除元素。另外数组还必须给定下标 才能访问其中的元素,但在对数组元素进行遍历的时候,这个下标并不是很有用。
.NET扩展了对许多在不同环境下使用的其他数据结构的支持,不仅如此,.NET还有许多接口,类实现这些接口后,就可以声明它们支持某种数据结构类型的全部功能。下面介绍3个这样的结构:(下面几种结构类都在System.Collections命名空间中)
1、数组列表
2、集合
3、字典
1.1 数组列表(System.Collections.ArrayList)
ArrayList和StringBuilder相似,其容量可以自动增长。即初始化的时候可以指定其容量(默认值是16),当添加的对象数超出其容量的时候,ArrayList的容量就会自动增大,新增的内存区域可以是成倍增长。
下面是ArrayList的一些基本功能:
ArrayList vectors = new ArrayList(20);
//或者使用默认值
ArrayList vectors = new ArrayList();
//添加元素
vectors.Add(new vector(2,1,2));
//访问元素
vector element1 = (vector)vectors[1];
//插入元素
vectors.Insert(1,new vector(2,4,2));
//删除元素
vectors.RemoveAt(1);
//可以改变ArrayList的容量
vectors.Capacity = 30;
//获取列表中元素的个数
int eleCount = vectors.Count;
//数据列表和数组之间的转换
vector[] vectorsArray = new vector[vectors.Count];
for(int i = 0; i<vectors.Count; i++)
{
vectorsArray[i] = (vector)vectors[i];
}
//或者使用默认值
ArrayList vectors = new ArrayList();
//添加元素
vectors.Add(new vector(2,1,2));
//访问元素
vector element1 = (vector)vectors[1];
//插入元素
vectors.Insert(1,new vector(2,4,2));
//删除元素
vectors.RemoveAt(1);
//可以改变ArrayList的容量
vectors.Capacity = 30;
//获取列表中元素的个数
int eleCount = vectors.Count;
//数据列表和数组之间的转换
vector[] vectorsArray = new vector[vectors.Count];
for(int i = 0; i<vectors.Count; i++)
{
vectorsArray[i] = (vector)vectors[i];
}
1.2 集合
集合表示一组可以通过遍历每个元素来访问的一组对象,特别是可以使用foreach循环来访问它们。使用foreach循环是集合的主要目的,并无其它特性。
集合要能使用foreach循环,必须实现System.Collections.IEnumerable接口
interface IEnumerable
{
object Current {get;}
bool MoveNext();
void Reset();
}
下面给出一个例子,对Vector结构实现IEnumerable接口。{
object Current {get;}
bool MoveNext();
void Reset();
}
struct Vector : IEnumerable
{
public double x, y, z;
public IEnumerable GetEnumerator()
{
return new VectorEnumerator(this);
}
private class VectorEnumerator:IEnumerable
{
private Vector theVector;
private int location;
public VectorEnumerator(Vector theVector)
{
this.theVector = theVector;
this.location = -1;
}
public bool MoveNext()
{
++location;
return (location > 2) ? false : true;
}
public object Current
{
get
{
if (location < 0 || location > 3)
{
throw new InvalidOperationException("the enumerator is either before the first element or after the last element of the vector");
}
return theVector[(uint)location];
}
}
public void Reset()
{
location = -1;
}
}
}
{
public double x, y, z;
public IEnumerable GetEnumerator()
{
return new VectorEnumerator(this);
}
private class VectorEnumerator:IEnumerable
{
private Vector theVector;
private int location;
public VectorEnumerator(Vector theVector)
{
this.theVector = theVector;
this.location = -1;
}
public bool MoveNext()
{
++location;
return (location > 2) ? false : true;
}
public object Current
{
get
{
if (location < 0 || location > 3)
{
throw new InvalidOperationException("the enumerator is either before the first element or after the last element of the vector");
}
return theVector[(uint)location];
}
}
public void Reset()
{
location = -1;
}
}
}
1.3 字典
字典还可以称为映射或散列表,这种数据结构允许按照某个键来访问元素,键可以是任意数据类型,也可以向字典任意添加和删除元素。
在.NET中基本的字典是由HashTable类来表示的,其键和条目都是object类型。其基本用法如下:
HashTable employees = new HashTable(53);//用素数初始化指定HashTable的容量,工作效率高
//添加元素
employees.Add(id,data);//id和data都是对象数据
//获取元素
EmployeeData data = employees[id];
//删除元素
employees.Remove(id);
//获取元素个数
int nEmployee = employees.Count;
下面是一个字典的实例://添加元素
employees.Add(id,data);//id和data都是对象数据
//获取元素
EmployeeData data = employees[id];
//删除元素
employees.Remove(id);
//获取元素个数
int nEmployee = employees.Count;
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ZidianTest
{
class Program
{
static void Main(string[] args)
{
TestHarness harness = new TestHarness();
harness.Run();
}
}
class EmployeeID //键值对象,必须重写Equals()和GetHashCode()
{
private readonly char prefix;
private readonly int number;
public EmployeeID(string id)
{
prefix = (id.ToUpper())[0];
number = int.Parse(id.Substring(1, 3));
}
public override string ToString()
{
return prefix.ToString() + string.Format("{0,3:000}",number);
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override bool Equals(object obj)
{
EmployeeID rhs = obj as EmployeeID;
if (rhs == null)
{
return false;
}
if (prefix == rhs.prefix && number == rhs.number)
{
return true;
}
return false;
}
}
class EmployeeDate //数据对象
{
private string name;
private decimal salary;
private EmployeeID id;
public EmployeeDate(EmployeeID id, string name, decimal salary)
{
this.id = id;
this.salary = salary;
this.name = name;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder(id.ToString(), 100);
sb.Append(":");
sb.Append(string.Format("{0,-20}", name));
sb.Append(" ");
sb.Append(string.Format("{0:C}", salary));
return sb.ToString();
}
}
class TestHarness //测试类
{
System.Collections.Hashtable employees = new Hashtable(31);
public void Run()
{
EmployeeID idMortimer = new EmployeeID("B001");
EmployeeDate mortimer = new EmployeeDate(idMortimer, "Mortimer", 100000.00M);
EmployeeID idArabel = new EmployeeID("W234");
EmployeeDate arabel = new EmployeeDate(idArabel, "Arabel Jones", 10000.00M);
employees.Add(idMortimer, mortimer);
employees.Add(idArabel, arabel);
while (true)
{
try
{
Console.Write("Enter employee ID(format:A999,X to exit)>");
string userInput = Console.ReadLine();
userInput = userInput.ToUpper();
if (userInput == "X")
{
return;
}
EmployeeID id = new EmployeeID(userInput);
DisplayData(id);
}
catch (Exception e)
{
Console.WriteLine("Exception occurred. Did you user the correct format for the employee ID?");
Console.WriteLine(e.Message);
Console.WriteLine();
}
Console.WriteLine();
}
}
private void DisplayData(EmployeeID id)
{
object empobj = employees[id];
if (empobj != null)
{
EmployeeDate employee = (EmployeeDate)empobj;
Console.WriteLine("Employee:" + employee.ToString());
}
else
{
Console.WriteLine("Employee not found:ID=" + id);
}
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ZidianTest
{
class Program
{
static void Main(string[] args)
{
TestHarness harness = new TestHarness();
harness.Run();
}
}
class EmployeeID //键值对象,必须重写Equals()和GetHashCode()
{
private readonly char prefix;
private readonly int number;
public EmployeeID(string id)
{
prefix = (id.ToUpper())[0];
number = int.Parse(id.Substring(1, 3));
}
public override string ToString()
{
return prefix.ToString() + string.Format("{0,3:000}",number);
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override bool Equals(object obj)
{
EmployeeID rhs = obj as EmployeeID;
if (rhs == null)
{
return false;
}
if (prefix == rhs.prefix && number == rhs.number)
{
return true;
}
return false;
}
}
class EmployeeDate //数据对象
{
private string name;
private decimal salary;
private EmployeeID id;
public EmployeeDate(EmployeeID id, string name, decimal salary)
{
this.id = id;
this.salary = salary;
this.name = name;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder(id.ToString(), 100);
sb.Append(":");
sb.Append(string.Format("{0,-20}", name));
sb.Append(" ");
sb.Append(string.Format("{0:C}", salary));
return sb.ToString();
}
}
class TestHarness //测试类
{
System.Collections.Hashtable employees = new Hashtable(31);
public void Run()
{
EmployeeID idMortimer = new EmployeeID("B001");
EmployeeDate mortimer = new EmployeeDate(idMortimer, "Mortimer", 100000.00M);
EmployeeID idArabel = new EmployeeID("W234");
EmployeeDate arabel = new EmployeeDate(idArabel, "Arabel Jones", 10000.00M);
employees.Add(idMortimer, mortimer);
employees.Add(idArabel, arabel);
while (true)
{
try
{
Console.Write("Enter employee ID(format:A999,X to exit)>");
string userInput = Console.ReadLine();
userInput = userInput.ToUpper();
if (userInput == "X")
{
return;
}
EmployeeID id = new EmployeeID(userInput);
DisplayData(id);
}
catch (Exception e)
{
Console.WriteLine("Exception occurred. Did you user the correct format for the employee ID?");
Console.WriteLine(e.Message);
Console.WriteLine();
}
Console.WriteLine();
}
}
private void DisplayData(EmployeeID id)
{
object empobj = employees[id];
if (empobj != null)
{
EmployeeDate employee = (EmployeeDate)empobj;
Console.WriteLine("Employee:" + employee.ToString());
}
else
{
Console.WriteLine("Employee not found:ID=" + id);
}
}
}
}