IList与ArrayList简单实现与区别

作者:袖梨 2022-06-25

ilist与arraylist简单实现与区别
第一个心得,是我看某本书提到,ilist用起来要比arraylist快

//测试list容器的功能

void main(void)
{
    //list1对象初始为空
    intlist list1;
    //list2对象最初有10个值为6的元素
    intlist list2(10,6);
    //list3对象最初有3个值为6的元素
    intlist list3(list2.begin(),--list2.end());
   
    //声明一个名为i的双向迭代器
    intlist::iterator i;
   
    //从前向后显示各list对象的元素
    put_list(list1,"list1");
    put_list(list2,"list2");
    put_list(list3,"list3");
   
    //从list1序列后面添加两个元素
    list1.push_back(2);
    list1.push_back(4);
    cout<<"list1.push_back(2) and list1.push_back(4):"<     put_list(list1,"list1");
   
    //从list1序列前面添加两个元素
    list1.push_front(5);
    list1.push_front(7);
    cout<<"list1.push_front(5) and list1.push_front(7):"<     put_list(list1,"list1");
   
    //在list1序列中间插入数据
    list1.insert(++list1.begin(),3,9);
    cout<<"list1.insert(list1.begin()+1,3,9):"<     put_list(list1,"list1");
   
    //测试引用类函数
    cout<<"list1.front()="<     cout<<"list1.back()="<    
    //从list1序列的前后各移去一个元素
    list1.pop_front();
    list1.pop_back();
    cout<<"list1.pop_front() and list1.pop_back():"<     put_list(list1,"list1");
   
    //清除list1中的第2个元素
    list1.erase(++list1.begin());
    cout<<"list1.erase(++list1.begin()):"<     put_list(list1,"list1");
   
    //对list2赋值并显示
    list2.assign(8,1);
    cout<<"list2.assign(8,1):"<     put_list(list2,"list2");
   
    //显示序列的状态信息
    cout<<"list1.max_size(): "<     cout<<"list1.size(): "<     cout<<"list1.empty(): "<    
    //list序列容器的运算
    put_list(list1,"list1");
    put_list(list3,"list3");
    cout<<"list1>list3: "<<(list1>list3)<     cout<<"list1    
    //对list1容器排序
    list1.sort();
    put_list(list1,"list1");
   
    //结合处理
    list1.splice(++list1.begin(), list3);
    put_list(list1,"list1");
    put_list(list3,"list3");
}


、如何使用arraylist
最简单的例子:


arraylist list = new arraylist();
for( int i=0;i<10;i++ ) //给数组增加10个int元素
         list.add(i);
//..程序做一些处理
list.removeat(5);//将第6个元素移除
for( int i=0;i<3;i++ ) //再增加3个元素
      list.add(i+20);
int32[] values = (int32[])list.toarray(typeof(int32));//返回arraylist包含的数组

这是一个简单的例子,虽然没有包含arraylist所有的方法,但是可以反映出arraylist最常用的用法。


3、arraylist重要的方法和属性
(1)构造器
arraylist提供了三个构造器:
public arraylist();
默认的构造器,将会以默认(16)的大小来初始化内部的数组
public arraylist(icollection);
用一个icollection对象来构造,并将该集合的元素添加到arraylist
public arraylist(int);
用指定的大小来初始化内部的数组
(2)issynchronized属性和arraylist.synchronized方法
issynchronized属性指示当前的arraylist实例是否支持线程同步,而arraylist.synchronized静态方法则会返回一个arraylist的线程同步的封装。
如果使用非线程同步的实例,那么在多线程访问的时候,需要自己手动调用lock来保持线程同步,例如:


arraylist list = new arraylist();
//...
lock( list.syncroot ) //当arraylist为非线程包装的时候,syncroot属性其实就是它自己,但是为了满足icollection的syncroot定义,这里还是使用syncroot来保持源代码的规范性
...{
list.add( “add a item” );
}

如果使用arraylist.synchronized方法返回的实例,那么就不用考虑线程同步的问题,这个实例本身就是线程安全的,实际上arraylist内部实现了一个保证线程同步的内部类,arraylist.synchronized返回的就是这个类的实例,它里面的每个属性都是用了lock关键字来保证线程同步。
****
但是,使用这个方法(arraylist.synchronized)并不能保证枚举的同步,例如,一个线程正在删除或添加集合项,而另一个线程同时进行枚举,这时枚举将会抛出异常。所以,在枚举的时候,你必须明确使用 syncroot 锁定这个集合。
 
hashtable与arraylist关于线程安全性的使用方法类似

list和arraylist的定义在注释中给出,可以看出来其实都差不多。arraylist只是多了icloneable,还少了几个泛型接口继承。

在后面代码中都用add方法向list中添加int类型数据,然后通过foreach形式枚举数据,注意!枚举部分的代码是有问题的,我们在(下)中会提到。

这里还要推荐一个非常棒的工具ilspy,是sharpdevelop开发的,强烈建议dotnet程序员都下载使用。

我把ilspy disassemble出来的c#代码和il代码分别列在后面。注意对于arraylist的foreach语句,c#形式的代码与源代码有些差别(79 到96行),编译器加入一个ienumerator enumerator2 = cfromarraylist.getenumerator();本地变量。

另外使用int num5 = (int)enumerator2.current;这样访问iterator。而且还加入了idisposable的finally部分。

再继续看il代码部分,对于list形式,il代码没有box装箱指令,而arraylist在145行有个box指令,这是性能差别之一。
但是奇怪的是,在枚举部分,ilspy生成的(以及ildasm)il代码,对于arraylist和list而言,基本上差别不大,一样也有对 movenext和current以及idisposable接口的调用。

只不过arraylist多出unbox和box的指令。

运行结果如我们所料,list要比arraylist快不少。

 

相关文章

精彩推荐