- - PR -
ArrayList.IndexOfの使用方法について
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-10-11 21:50
お世話になっております。
アキミです。 独自のクラスを作成して、そのクラスをArrayListによって 配列としました。
このクラスに対して
というように、データベースから取得したレコードを入れています。 このRecord(ArrayList)に対して、「Textが"ShopName"というTableFieldのインデックスを取得する」という方法でindexOfを使用したいのですが、その方法がわかりません。 テストとしてRecord.indexOf(new TableField("ShopName","7-11"))という方法をしてみても「-1」が入ってきてしまいます。 とりあえず、今は作成したTableFieldクラスを使用せずに、
といった感じでデータを追加して
という風に取得しています。 前述のような、作成したクラスで検索が出来れば美しそうな感じなんですが。 なにかいい方法はないでしょうか? | ||||||||||||||||
|
投稿日時: 2003-10-11 22:21
こんにちわ。諸農です。
ちゃんと確認していませんが、TableFieldクラスのToString()メソッドを オーバーライドして、どちらかのフィールドに格納されている文字列を 返すようにしてみてはいかがでしょうか。 ではでは(^^)/ _________________ 諸農和岳 Powered by Turbo Delphi & Microsoft Visual Studio 2005 十兵衛@わんくま同盟 http://blogs.wankuma.com/jubei/ | ||||||||||||||||
|
投稿日時: 2003-10-11 22:50
ArrayListに格納するクラス(ここではTableFieldクラス)で、Equalsメソッドをオーバーライドする事で、比較方法をカスタマイズできます。 ※ArrayList.IndexOfのドキュメントより このメソッドは、 Object.Equals を呼び出して、等しいかどうかを判断します。 ただし、Textフィールドが等しい場合に同じオブジェクトとみなしてよい場合にしか使えません。 調べてみましたが、ArrayListの検索で比較方法を自由に指定出来るものはなさそうですね。 # BinarySearchならIComaparerを指定出来るようですが、 # この場合は先にソートが必要になります。 追加順とインデックスが重要なのであれば仕方ないですが、そうでなければディクショナリ系のものを使う方がシンプルかもしれません。 # もしくは、上述のようにソートしてBinarySearchを使うか。 | ||||||||||||||||
|
投稿日時: 2003-10-11 23:21
参照の等価性と値の等価性の違いです。
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/dnguinet/htm/drguinet01312001.asp この辺の細かい話は、↑に書いてありますので、参照してください(問題の箇所は一部分に埋もれてます…Equalsのところ)。
この場合、classのデフォルトでの Equals() メソッドは参照の等価性を利用しますので、新しく作ったオブジェクトはたとえ値が同じでも別のものと判断されます。別のものなので、「ArrayList.IndexOf メソッドは格納されていないと判断」→「-1がかえってくる」わけです。 そのクラスを値の等価性において等価とみなすようにするためには Equals() メソッドをオーバーライドします。ただ、これはかなりコツがいる作業になるので(説明するのは骨)、参考となるコードを挙げておきますね(C#ですみませぬ)。
…かなり適当にかいたので問題があったら誰か指摘してください。 ちなみに、めんどくさい/わからないのならデータを保持する(ArrayListに格納する)classをstructにしてみてください。何も考えずに ArrayList.IndexOf メソッドが期待通りの動作をすると思います。 | ||||||||||||||||
|
投稿日時: 2003-10-12 05:04
Jubeiさん、なちゃさん、yaさん、ありがとうございます。
参考のリンクとご説明により、できない理由が見えてきました。 値型と参照型は理解しているつもりで、まだまだ全然だめなようです…。 Equalsをオーバーライドするのが一番素敵な方法だと思うのですが、 今現在はその様な力もないのが現状でして、それはもう少しレベルアップ したときのお楽しみとして取っておこうと思います。 yaさんのあげて頂いた、もう一つの方法である 「Structure」での処理をやってみようと思いました。 DBFieldクラスを
ところが
考えてみれば、「TextがNothing」なわけで、一致しないというのは正しい動きだと思います。 toStringをオーバーライドしてみたのですが、結果は変わりません。
「なにか」をオーバーライドすれば出来る…ような気もするのですが。 その「なにか」が解らない次第です。 勉強が足りないのはわかっているのですが、お知恵を拝借させていただければ幸いです。 よろしくお願い致します。 | ||||||||||||||||
|
投稿日時: 2003-10-12 09:48
何かをオーバーライドする事による方法は、Equalsをオーバーライドしかないと思います(ArrayListのIndexOfの動作より)。 Structにした場合に何が起こるかというと、デフォルトのEquals実装が、オブジェクトの参照の比較ではなく、各メンバのEquals呼び出しによる実装に変わるということだったと思います。 # 微妙に間違ってるかもしれませんが、そういうイメージです。 ですので、自分で作成した構造体では、クラスと違い、Equalsをオーバーライドしなくても自動的にフィールドの値による比較が出来る事になります。 # 多分リフレクションで呼び出すとかの可能性があるので、 # パフォーマンスは悪いかもしれません。 今回のように、特定のフィールドの値で比較する必要がある場合には、やっぱりEqualsをオーバーライドする必要があります(それが問題ないかともかくとして)。 あと、ArrayListなどのコレクションに格納するのが前提のオブジェクトは、構造体にはしない方が良いかもしれません。 | ||||||||||||||||
|
投稿日時: 2003-10-12 14:48
こんにちわ。諸農です。
申し訳ないです。既に皆さんからのRESにもあるように、 実装はEquals()メソッドをオーバーライドするのが正しいと思います。 v1.1のSDKのArrayList.IndexOf()の説明にはハッキリと、
と書かれていました。 yaさんから提示されているコードは、かなり参考になると思います。 その他にも、C#を対象に書かれた書籍ですが、 『プログラミング.NET Framework』(マイクロソフトプレス、日経BP) も参考になるかと思います。 ではでは(^^)/ _________________ 諸農和岳 Powered by Turbo Delphi & Microsoft Visual Studio 2005 十兵衛@わんくま同盟 http://blogs.wankuma.com/jubei/ | ||||||||||||||||
|
投稿日時: 2003-10-12 15:54
すみません、特定フィールドでの検索だったんですね。
なちゃさん等もおっしゃっているように Equals メソッドでしか ArrayList.IndexOf の動作は変更できません。 ただ、この場合、等価性を利用するのはちょっとまずい気がします。ほかのフィールドが違っていても等価であると判断してもよいか、となってこれは一般的には駄目でしょう。 特定フィールドでの検索機能を持ちたい場合は別にそのためのコレクションを持つ(すでに実装なさっている方法です)か、自分で作るのが一般的でしょう(ArrayList ではこの機能を実現するのは BinarySearch が一番近いですが、これは ArrayList が Sort されている必要があります)。 どうしてもいまの実装で美しくないと感じてしまうのなら、ArrayListを使わずそのデータの格納に特化した(TableField クラスしか格納できない & お望みの動作である Find メソッドみたいなものを実装している)コレクションクラスを自分で作りましょう。 ちなみに現状のコレクションを2つ持つという実装のままで行くなら、検索用のコレクションは、Hashtable か SortedList にしたほうがよいですよ。 |