Javaにおけるイテレータパターン:順次要素アクセスをマスターする
別名
- カーソル
イテレータデザインパターンの目的
Javaのイテレータデザインパターンは、集約オブジェクトの要素に、その内部表現を公開することなく順次アクセスする方法を提供します。この振る舞いパターンは、効率的なコレクション走査に不可欠です。
実例を用いたイテレータパターンの詳細な説明
実例
フィクション、ノンフィクション、科学など、さまざまなセクションに整理された膨大な蔵書を持つ図書館を訪れることを想像してみてください。すべての棚を自分で探す代わりに、司書は各セクションに特定のガイドブックまたはデジタルカタログを提供します。このガイドブックは「イテレータ」として機能し、棚にどのように本が整理されているかを知らなくても、セクションごとに本を閲覧したり、特定の種類の本にスキップしたりすることができます。各ガイドブックは、そのセクションの走査を処理し、本にアクセスするための整合性のある効率的な方法を提供します。これは、イテレータデザインパターンがソフトウェアアプリケーションでさまざまなデータ構造を走査するための統一された方法を提供する方法とよく似ています。
簡単に言うと
Javaイテレータデザインパターンは、コレクションの内部構造を公開することなく、コレクションの要素に順次アクセスする方法を提供します。このパターンは、Javaプログラミングで効率的なデータアクセスに広く使用されています。
Wikipediaによると
オブジェクト指向プログラミングにおいて、イテレータパターンは、イテレータを使用してコンテナをトラバースし、コンテナの要素にアクセスするデザインパターンです。
Javaにおけるイテレータパターンのプログラミング例
Javaイテレータデザインパターンの例における主なクラスは、アイテムを含む`TreasureChest`です。これは、Javaで効率的なコレクション走査のためにイテレータを実装および使用する方法を示しています。
public class TreasureChest {
private final List<Item> items;
public TreasureChest() {
items = List.of(
new Item(ItemType.POTION, "Potion of courage"),
new Item(ItemType.RING, "Ring of shadows"),
new Item(ItemType.POTION, "Potion of wisdom"),
new Item(ItemType.POTION, "Potion of blood"),
new Item(ItemType.WEAPON, "Sword of silver +1"),
new Item(ItemType.POTION, "Potion of rust"),
new Item(ItemType.POTION, "Potion of healing"),
new Item(ItemType.RING, "Ring of armor"),
new Item(ItemType.WEAPON, "Steel halberd"),
new Item(ItemType.WEAPON, "Dagger of poison"));
}
public Iterator<Item> iterator(ItemType itemType) {
return new TreasureChestItemIterator(this, itemType);
}
public List<Item> getItems() {
return new ArrayList<>(items);
}
}
`Item`クラスはこちら
public class Item {
private ItemType type;
private final String name;
public Item(ItemType type, String name) {
this.setType(type);
this.name = name;
}
@Override
public String toString() {
return name;
}
public ItemType getType() {
return type;
}
public final void setType(ItemType type) {
this.type = type;
}
}
public enum ItemType {
ANY, WEAPON, RING, POTION
}
`Iterator`インターフェースは非常にシンプルです。
public interface Iterator<T> {
boolean hasNext();
T next();
}
次の例では、さまざまな種類のイテレータを示します。
@Slf4j
public class App {
private static final TreasureChest TREASURE_CHEST = new TreasureChest();
private static void demonstrateTreasureChestIteratorForType(ItemType itemType) {
LOGGER.info("------------------------");
LOGGER.info("Item Iterator for ItemType " + itemType + ": ");
var itemIterator = TREASURE_CHEST.iterator(itemType);
while (itemIterator.hasNext()) {
LOGGER.info(itemIterator.next().toString());
}
}
private static void demonstrateBstIterator() {
LOGGER.info("------------------------");
LOGGER.info("BST Iterator: ");
var root = buildIntegerBst();
var bstIterator = new BstIterator<>(root);
while (bstIterator.hasNext()) {
LOGGER.info("Next node: " + bstIterator.next().getVal());
}
}
private static TreeNode<Integer> buildIntegerBst() {
var root = new TreeNode<>(8);
root.insert(3);
root.insert(10);
root.insert(1);
root.insert(6);
root.insert(14);
root.insert(4);
root.insert(7);
root.insert(13);
return root;
}
public static void main(String[] args) {
demonstrateTreasureChestIteratorForType(RING);
demonstrateTreasureChestIteratorForType(POTION);
demonstrateTreasureChestIteratorForType(WEAPON);
demonstrateTreasureChestIteratorForType(ANY);
demonstrateBstIterator();
}
}
プログラム出力
13:36:37.087 [main] INFO com.iluwatar.iterator.App -- ------------------------
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Item Iterator for ItemType RING:
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Ring of shadows
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Ring of armor
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- ------------------------
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Item Iterator for ItemType POTION:
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of courage
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of wisdom
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of blood
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of rust
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of healing
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- ------------------------
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Item Iterator for ItemType WEAPON:
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Sword of silver +1
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Steel halberd
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Dagger of poison
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- ------------------------
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Item Iterator for ItemType ANY:
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of courage
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Ring of shadows
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of wisdom
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of blood
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Sword of silver +1
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of rust
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of healing
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Ring of armor
13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Steel halberd
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Dagger of poison
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- ------------------------
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- BST Iterator:
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 1
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 3
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 4
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 6
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 7
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 8
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 10
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 13
13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 14
Javaでイテレータパターンを使用する場合
Javaでイテレータデザインパターンを使用する
- 集約オブジェクトの内容に、その内部表現を公開することなくアクセスするため。
- 集約オブジェクトの複数回のトラバースをサポートするため。
- さまざまな集約構造をトラバースするための統一されたインターフェースを提供するため。
イテレータパターンJavaチュートリアル
Javaにおけるイテレータパターンの実用的なアプリケーション
- Javaコレクションフレームワークは、コレクションをトラバースするためのさまざまな方法を可能にするために、イテレータを広く使用しています。
- データベースは、SQLクエリから取得したデータレコードをナビゲートするために、しばしばイテレータを使用します。
- java.util.Iterator
- java.util.Enumeration
イテレータパターンのメリットとトレードオフ
メリット
- 反復に使用されるデータ構造とアルゴリズム間の結合を削減します。
- さまざまな種類のデータ構造を反復処理するための統一されたインターフェースを提供し、コードの再利用性と柔軟性を向上させます。
トレードオフ
- イテレータオブジェクトを使用することによるオーバーヘッドにより、直接的なトラバース方法と比較してパフォーマンスがわずかに低下する可能性があります。
- 複雑な集約構造には、管理や拡張が困難な複雑なイテレータが必要になる場合があります。
関連するJavaデザインパターン
- コンポジット:イテレータは、コンポジットツリーをトラバースするために頻繁に使用されます。
- ファクトリーメソッド:さまざまなデータ構造に適切なイテレータを作成するために使用されます。
- ビジター:オブジェクト構造の要素に操作を適用するために、イテレータと共に使用できます。