- PR -

Iteratorについて

投稿者投稿内容
eiji
常連さん
会議室デビュー日: 2003/07/23
投稿数: 32
投稿日時: 2003-10-15 13:49
Iterator を使用する場合のメリット/ディメリットは、何があるんでしょうか?
(どのような場合には、Iteratorを使用して、
 どのような場合は、使用しない方がよいっといった指針のような物はあるんでしょうか?)


## 例えば、Listを要素数分ループさせる場合に、
## Iteratorでもループできますし、size()でもループできると思います。

ArrayList list = new ArrayList();

Iterator i = list.iterator();
while (i.hasNext()) {

}

for (int i=0; i<list.size(); i++) {

}
ぽん
大ベテラン
会議室デビュー日: 2003/05/13
投稿数: 157
投稿日時: 2003-10-15 13:57
ここを読んでみてください。
http://www.dmz.hitachi-sk.co.jp/Java/Tech/pattern/gof/iterator.html
swat
常連さん
会議室デビュー日: 2002/03/21
投稿数: 33
お住まい・勤務地: 埼玉県
投稿日時: 2003-10-15 14:02
swatです。

Iteratorのばあい、iterator生成時点でのリストのすべての要素への順次アクセスが出来ることを保証してくれていたような気がします。

自分でforでまわした場合、すべての要素に順次アクセスできるかどうかはコーディング次第ですので、必ずすべての要素にアクセスしたい、というのなら、Iterator、ということかもしれません。

それと、Map系のコレクションクラスの順次アクセスにはiteratorが便利ですね。

#私も厳密にはわかっていません。識者のフォローを期待します。

[ メッセージ編集済み 編集者: swat 編集日時 2003-10-15 14:02 ]
tabby
ベテラン
会議室デビュー日: 2002/06/26
投稿数: 55
お住まい・勤務地: 埼玉県・東京都
投稿日時: 2003-10-15 14:13
対象によって変えるってのがいいのではないでしょうか?

ArrayListやVectorの場合はsize()+get(n)
それ以外はIterator

メソッド内だけで完結するのであれば、ロジックにあわせて
クラスを選べばいいかと。
Emacs信者
常連さん
会議室デビュー日: 2003/08/10
投稿数: 38
投稿日時: 2003-10-15 14:37
Iteratorの場合は、もしイテレート中に、Iteratorを取り出したCollectionやMapの内容に変更があった場合には、ConcurrentModificationExceptionがスローされます。

それに対して、カウンタでぐるぐる回す方法だと、内容に変更があってもConcurrentModificationExceptionはスローされません。

つまり、Iteratorの場合は、Iteratorを取り出した時点でその内容が確定します。


※ 上記の話は、CollectionやMapの実装にArrayListやHashMap(CoreAPIのクラス)を使用した場合の話です。
カスタム実装を使用した場合は必ずしも上記の通りではありません。
eiji
常連さん
会議室デビュー日: 2003/07/23
投稿数: 32
投稿日時: 2003-10-15 14:49
皆さんご返信ありがとうございます。

私の場合、内部構造を隠蔽したい場合(ユーティリティー等)は、Iterator を
使用し、その他は、size()+ get(n) を使用していましが、
本当はどう違うんだろうという疑問がわき投稿しました。
※Map系の場合は、順次アクセスする事は稀なんで、Listまで変換していました
 swat様の言う通り、Map系のコレクションクラスの順次アクセスには
 iteratorを使用した方がよさそうですね。

で、結論はこんな感じでしょうか?
デザインパターンでは、Iteratorを使用すべきだと思いますが、
パフォーマンスが若干悪い・コーディングが面倒等々の理由があるので
以下の3点を念頭に、後は、ケースBYケース にする。
1.内部構造を隠蔽したい場合は、Iterator
2.Listを使用する場合は、size()+ get(n)
3.Map系の、順次アクセスする場合は、Iterator

間違っていれば、ご指摘して下さい。

さくらば
大ベテラン
会議室デビュー日: 2002/11/12
投稿数: 145
投稿日時: 2003-10-15 15:00
こんにちは、さくらばです。

引用:

eijiさんの書き込み (2003-10-15 14:49) より:
で、結論はこんな感じでしょうか?
デザインパターンでは、Iteratorを使用すべきだと思いますが、
パフォーマンスが若干悪い・コーディングが面倒等々の理由があるので
以下の3点を念頭に、後は、ケースBYケース にする。
1.内部構造を隠蔽したい場合は、Iterator
2.Listを使用する場合は、size()+ get(n)
3.Map系の、順次アクセスする場合は、Iterator




2. は問題ありです。というのも LinkedList の get(n) はむちゃくちゃ遅いのですが、
Iterator を使用した場合はとても速くアクセスできます。

その代わりに次のようなルールがいいと思います。

Collection インタフェースをインプリメントしているクラスのうち
1. java.util.RandomAccess インタフェースをインプリメントしているものは get(n)
2. RandomAccess インタフェースをインプリメントしていないものは Iterator を使用する

1. の条件に合うのは ArrayList, Vector
2. の方は LinkedList, HashSet, LinkedHashSet などです。

Emacs信者
常連さん
会議室デビュー日: 2003/08/10
投稿数: 38
投稿日時: 2003-10-15 15:16
Iteratorを使用する場合は、「コレクションの全要素に対して順次アクセスする」という意図がソースを見るだけで伝わるというメリットがあるのではないでしょうか。
それに対して、カウンタを使用する方法だと、コメントが必要になる場合もあります。
なので、僕の場合はできる限りIteratorを使用しています。

ただし、さくらばさんが指摘する通り、コレクションの特性や要素数によっては性能の差が顕著になるので、場面にあわせた使いわけが必要になることもあります。

でも、そんな場面は頻繁には出てこないと思っています。

コード:

//全要素を先頭から順に出力(Iterator)
for(final Iterator iter=list.iterator() ; iter.hasNext() ; ){
System.out.println( iter.next() );
}

//全要素を先頭から順に出力(カウンタ)
for(int i=0, M=list.size() ; i<M ; i++){
System.out.println( list.get(i) );
}

//「最後以外の」全要素を先頭から順に出力
//一つ上の例との違いがわかりにくい
for(int i=0, M=list.size()-1 ; i<M ; i++){
System.out.println( list.get(i) );
}




[ メッセージ編集済み 編集者: Emacs信者 編集日時 2003-10-15 15:17 ]

スキルアップ/キャリアアップ(JOB@IT)