JScript.NET  新JavaScript入門  JavaScript,Neo-Generation  DOM  WSH  掲示板  表紙
Written 5/28/03
JScript.NET
ArrayList
概要
ArrayListは自動的にサイズが大きくなる配列です。
C++のSTLを知っている人は分かると思いますが、 たぶんvectorに似ています。
JScriptのArrayよりも便利な面もあり、 速度も格段に速いのでこれを使いましょう。
Add
自動的に配列が大きくなるとは、 次のように要素を追加していくにつれてサイズが大きくなることです。
    arraylist_add.js
    --------------------------------------
    import System;
    import System.Collections;
    
    var ary : ArrayList = new ArrayList();
    //要素を追加
    ary.Add("POSKA");
    ary.Add("マスカラ");
    ary.Add("100円玉");
    
    //要素を全て表示
    for(var i = 0; i < ary.Count; i++)   //i=0,1,2
        print(i + " : " + ary[i]);
 
Addメソッドで要素を追加していきます。 配列の大きさはCountで得ます。 要素へのアクセスは普通の配列と同様です。
Capacity
ArrayListには配列の大きさを表すCountとは別に格納できる要素の数を表す Capacityというプロパティがあります。
    arraylist_capacity.js
    --------------------------------------
    import System;
    import System.Collections;
    
    var ary : ArrayList = new ArrayList();
    print(ary.Capacity);      //16
    ary.Add("POSKA");
    ary.Add("マスカラ");
    ary.Add("100円玉");
    print(ary.Capacity);      //16
 
最初から16個分は確保されているようです。 さらにAddを繰り返していくと、その容量を超えた場合、容量は倍になります。
Capacityが変わるということは、 恐らく新たに領域を確保して要素をそこにコピーしなければならないと思われます (ホントはどうなのか知りませんが)。 最初から十分な領域を確保しておけばその動作がいらなくなり、 実行速度が上がると推測されます。
次のプログラムは漸化式、
    a0 = a1 = 1
    ai+2 = ai+1 + 1/ai (i >= 0)
 
で a200001 を求めます(本当は配列を使う必要はないのですが)。
    arraylist_add2.js
    ------------------------------------------
    import System;
    import System.Collections;
    
    var t : int = Environment.TickCount;
    var n : int = 200000;
    var a : ArrayList = new ArrayList();
    a.Add(1);
    a.Add(1);
    for(var i : int = 0; i < n; i++)
        a.Add(a[i+1] + 1 / a[i]);
    print(a[n+1]);
    print((Environment.TickCount - t) + "ms");
 
これに対して、最初に十分な領域を確保しておくのが次のコードです。
    arraylist_add3.js
    ------------------------------------
        ...
    var a : ArrayList = new ArrayList();
    a.Capacity = n + 2;      //領域確保
        ...
 
Capacityプロパティを大きくすることによって、 最初に領域を確保しています。
最初のは480msかかっていますが、このコードだと230msで済みました。
ちなみにJScriptのArrayオブジェクトを使った場合は、
    arraylist_add5.js
    --------------------------------
        ...
    var a = [ 1, 1 ];
    for(var i : int = 0; i < n; i++)
        a[i+2] = a[i+1] + 1 / a[i];
        ...
 
コードはいくぶん分かりやすくなりますが、1800msかかっています。
コピー
ArrayListの代入はArrayオブジェクトと同じようにアドレスを渡すことになります。
        ...
    var a : ArrayList = new ArrayList();
    for(var i = 0; i < 10; i++)
        a.Add(i);
    var b = a;           //アドレスを渡している
    print(b[9]);         //9
    a[9] = 0;
    print(b[9]);         //0
 
Arrayオブジェクトでは要素をすべてコピーするのは面倒でしたが、 ArrayListにはCloneというメソッドが用意されています。
        ...
    var b = a.Clone();   //簡易コピー
    a[9] = 0;
    print(b[9]);         //9
 
ただし、コピーするのは要素だけで、 その要素が参照型の場合、アドレスがコピーされることになります。
        ...
    var a : ArrayList = new ArrayList();
    a.Add([1, 2]);       //Arrayオブジェクトが要素
    var b = a.Clone();   //簡易コピー
    print(b[0][1]);      //2
    a[0][1] = 0;
    print(b[0][1]);      //0
 
Sort
ArrayListにはいろいろ便利なメソッドが多くありますが、 とても紹介しきれないので ArrayList メンバをご覧ください。
一つだけ、Sortメソッドを紹介しましょう。
次は、整数の配列を降順に並べて表示するプログラムです。
    revsort.js
    ----------------------------------------------------
    import System;
    import System.Collections;
    
    var a : ArrayList = new ArrayList();
    for(var i = 0; i < 10; i++)
        a.Add(i);
    a.Sort(new RevComp());        //降順にソート
    for(var p in a)
        print(p);
    
    //比較のメソッドを提供するクラス
    class RevComp implements IComparer {
        function Compare(a : Object, b : Object) : int {
            return int(b) - int(a);     //ここを変える
        };
    }
 
詳しく解説しませんが、上の「ここを変える」の部分を変えてください。 様々な並べ方が可能になります。 返り値はArrayオブジェクトのsortメソッド と同じです。 メソッドの引数はArrayオブジェクトでは関数でしたが、 ここではIComparerの実装となります。
詳しいことはインターフェイスをご覧ください。
配列, Arrayオブジェクト, exit