質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

iteratorパターン

iteratorパターンとは、オブジェクト指向プログラミングのデザインパターンです。コンテナオブジェクトの要素を列挙する手段を独立させることによって、コンテナの内部仕様に依存しない反復子を提供することを目的とします。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

ArrayList

Java用のタグです。arrayListはListインターフェースを実装した、リサイズ可能な配列用クラスです。

Q&A

4回答

1636閲覧

Iteratorを用いた、次の要素の型に応じて処理を変更する方法。

Chris1943

総合スコア1

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

iteratorパターン

iteratorパターンとは、オブジェクト指向プログラミングのデザインパターンです。コンテナオブジェクトの要素を列挙する手段を独立させることによって、コンテナの内部仕様に依存しない反復子を提供することを目的とします。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

ArrayList

Java用のタグです。arrayListはListインターフェースを実装した、リサイズ可能な配列用クラスです。

0グッド

0クリップ

投稿2021/10/31 09:39

編集2021/10/31 10:31

前提・実現したいこと

ListIteratorを用いてリストの操作を行っています。
クラスAnimalを継承しているクラスHuman,Cat,Dog,Birdがあります。
それぞれのインスタンスをArrayList<Animal>に追加していきます。今回は以下の順で追加します。

追加する順クラス
1Human
2Cat
3Dog
4Bird

【実現したいこと】
次の要素のクラスがBirdの時、そのクラスに特定の操作を実施する。
for文を用いた方法はわかるのですが、ListIteratorを用いた方法がわかりません。
今回でいうと、次の要素のクラスがBirdであるDogでのみ、changeFlag()を呼び出したいです。
お願いいたします。

発生している問題・エラーメッセージ

次の要素がクラスBirdであることは判別できても現在の要素(Dogのインスタンス)でのみ、changeFlag()を呼び出させる方法がわかりません。

該当のソースコード

Main

1ArrayList<Animal> list = new ArrayList<>(); 2Human human = new Human(); 3Cat cat = new Cat(); 4Dog dog = new Dog(); 5Bird bird = new Bird(); 6list.add(human); 7list.add(cat); 8list.add(dog); 9list.add(bird); 10 11// ここをIteratorにしたい 12for(int i = 0;i < list.size(); i++){ 13 // クラスがA4かチェック 14 if((i < list.size() - 1 )&&(list.get(i + 1) instanceof Bird)){ 15 list.get(i).changeFlag(); 16 } 17} 18 19// dogのみTrueになっているかチェック 20for(Animal animal : list){ 21 if(!animal.getFlag()){ 22 System.out.println("False"); 23 }else{ 24 System.out.println("True"); 25 } 26} 27

Animal

1class Animal{ 2 private boolean flag = false; 3 Animal(){} 4 5 void changeFlag(){ 6 flag = true; 7 } 8 9 boolean getFlag(){ 10 return flag; 11 } 12}

Human

1class Human extends Animal{ 2 Human(){} 3}

Cat

1class Cat extends Animal{ 2 Cat(){} 3}

Dog

1class Dog extends Animal{ 2 Dog(){} 3}

Bird

1class Bird extends Animal{ 2 Bird(){} 3}

試したこと

Main

1// ArrayList宣言から追加までは同じ 2ListIterator<Animal> iterator = list.listIterator(); 3while(iterator.hasNext()) { 4 // 次がBirdか判別 5 // 特定の処理 6}

補足情報(FW/ツールのバージョンなど)

特になし。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BeatStar

2021/10/31 09:49 編集

「特定の処理」とはなんでしょうか。それとArrayListに入れる予定のAとは何でしょうか。 A1,A2,A3... とは何でしょうか。 それらによって相当変わってきますよ。
coco_bauer

2021/10/31 09:57

少なくとも、クラスA、クラスA1、クラスA2、クラスA3、クラスA4を定義しているコードを示してもらわないと議論が始められないですよ。
Chris1943

2021/10/31 10:12

すみません、知りたかったのはIteratorの使用方法のみなのでクラス名等は端折りました。 分かりにくかったので追記します。少々お待ちください。
Chris1943

2021/10/31 10:40

追記しました。 仮のクラス名、メソッド名ですがやりたいこととしては合致しています。 宜しくお願いいたします。
jimbe

2021/10/31 11:00

コードのマークダウンの ``` の所に Main とか Dog とか書いている個所は(クラス名やファイル名を書く所では無く)言語名を書く所です。 全て java としてください。 ファイル名等は枠の外に書いてください。
xebme

2021/10/31 15:27

1つ前の要素を考えると簡単にならないでしょうか。 Iterator<T> iterator = list.iterator(); T previous = (iterator.hasNext()) ? iterator.next() : null; while (iterator.hasNext()) { T current = iterator.next(); previousがDog、currentがBirdのとき、previous.changeFlag() previous = current; }
guest

回答4

0

Animalの属性と並びに応じた処理

まず初めにAnimalを以下のように定義します。哺乳類、鳥類を表すメソッドと、changeFlagメソッド。changeFlag()はAnimalの振る舞いではないのでおかしいのですがこのままにしておきます。

Java

1public interface Animal { 2 boolean isMammal(); 3 boolean isBirds(); 4 void changeFlag(); 5}

ListIteratorをご希望ですがIteratorで目的を達成できます。一つ手前のインスタンスを保持するだけです。

Java

1 Iterator<Animal> iterator = list.iterator(); 2 Animal previous = (iterator.hasNext()) ? iterator.next() : null; 3 while (iterator.hasNext()) { 4 Animal current = iterator.next(); 5 if (previous.isMammal() && current.isBirds()) { 6 // 目的の機能を呼ぶ。 7 } 8 previous = current; 9 }

インスタンスのペアを生成するzip機能

changeFlag()はAnimalの振る舞いではないのでおかしいと申しましたが、changeFlag()はlist内のAnimalの並び情報を変更、保持するのが目的ですから、listに属するか、Animalのペアに属するか、あるいは、処理の中で一時的に利用するラムダ式のような位置付けになるかと思います。

ここでは、shiketaさんや先輩回答者に倣って、Animalのペアを考えてみます。型Tのペアを定義してIteratorを作ります。Java 17のrecord型でPairを定義します。

Java

1public record Pair<T>(T _1, T _2) {}

PairのIteratorを作ります。

Java

1 static <T> Iterator<Pair<T>> zip(final List<T> list) { 2 return new Iterator<Pair<T>>() { 3 final Iterator<T> iterator = list.iterator(); 4 T previous = (iterator.hasNext()) ? iterator.next() : null; 5 @Override 6 public boolean hasNext() { 7 return iterator.hasNext(); 8 } 9 @Override 10 public Pair<T> next() { 11 if (!iterator.hasNext()) { 12 throw new RuntimeException(); 13 } 14 Pair<T> result = new Pair<>(previous,iterator.next()); 15 previous = result._2(); 16 return result; 17 } 18 }; 19 }

PairのStreamも同様です。

Java

1 static <T> Stream<Pair<T>> zipStream_(List<T> list) { 2 Stream.Builder<Pair<T>> builder = Stream.builder(); 3 Iterator<T> iterator = list.iterator(); 4 T previous = (iterator.hasNext()) ? iterator.next() : null; 5 while (iterator.hasNext()) { 6 T current = iterator.next(); 7 builder.accept(new Pair<>(previous,current)); 8 previous = current; 9 } 10 return builder.build(); 11 }

補足情報を追記するかもしれません。

投稿2021/11/01 03:24

xebme

総合スコア1081

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Iteratorは、リストのどこか(通常は、先頭)から始めて、「次のデータを取り出して」というような操作を繰り返す(Iterate: 反復する)事を基本とする仕組みです。
どのデータが取り出されるかは、どの位置のデータに着目しているか(直前に取り出してデータがどこにあったか)によって決まります。
取り出すべきデータが無くなったら、動作を終了します。

質問に書かれているプログラムでは、以下の操作をループで繰り返しています。

aData = list.get(i + 1) i = i + 1; //データ取得市を1つ進める

リストが次の値を取り出す next()というイテレータを持っていたら、以下のような操作をループで繰り返せば良いことになります。

newdata = somelist.next(); //取得位置を1つ進めて、データを取得する(データの末尾まで行っていたら、nulを返す)

だいたい、おこんな感じです。(雰囲気を感じ取ってもらえればという意図で回答しました)

投稿2021/10/31 13:01

coco_bauer

総合スコア6915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

https://teratail.com/questions/54055の回答にあるzipを定義してみてはいかがかと。

  1. 元のリストと、そのリストの二番からの要素をペアにする。
  2. ペアの片側は現在の要素で、もう片側が次の要素。
  3. 先読みしなくても、次の要素がわかる。

先に挙げた回答ではScalaでどうぞとありますが、KotlinのListにもzipメソッドがある。こんな感じ。

kotlin

1object ZipSample { 2 interface Animal 3 class Human : Animal 4 class Cat : Animal 5 class Dog : Animal 6 class Bird : Animal 7 8 @JvmStatic 9 fun main(args: Array<String>) { 10 val list = listOf(Human(), Cat(), Dog(), Bird()) 11 12 list.zip(list.drop(1)) 13 .forEach { (a, b) -> 14 println("${a::class.simpleName} : ${b::class.simpleName}") 15 } 16 //Human : Cat 17 //Cat : Dog 18 //Dog : Bird 19 20 list.zip(list.drop(1)) 21 .forEach { (a, b) -> 22 if (b is Bird) { 23 println("${a::class.simpleName}. next ${b::class.simpleName}") 24 } 25 } 26 // Dog. next Bird 27 } 28}

投稿2021/10/31 11:25

shiketa

総合スコア3971

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Iterator は通常、対象要素群に対して一律の処理を行うような場合に有効な手段で、現在位置の要素と他位置の要素を使うような場合には(ListIteratorでも next したり previous したりと)面倒なだけです。
配列のほうが簡単かと思います。

投稿2021/10/31 11:05

jimbe

総合スコア12646

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問