みなさまこんにちは。
Numataです。
今回はremoveメソッドの解説です。
コレクションの学習をしていて、インスタンスを消去するという
作業が出てきたときに行き詰まる箇所かと思います。
removeメソッドはとても便利ですが、使うときに注意すべきこともあるので、
一番便利な使い方と注意点について解説していきます!
それではいきましょう!
もくじ
コレクションからインスタンスを削除します
removeメソッドの働きは何といってもこれです。
コレクションとは、インスタンスの集まりです。
おおよそ配列のようなモノですが、配列よりも柔軟性があります。
配列では、要素を削除することはできません。
しかし、コレクションではそれが可能なのです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class Main { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd"); list.add("eee"); //コレクションでは要素を削除することができる list.remove(3); //配列では、一度値を入れてしまうと、nullを代入するしかない String[] array = {"aaa","bbb","ccc","ddd","eee"}; array[3] = null; } } |
なぜインスタンスを削除できるかというと、
コレクションは、要素数が決まっていないから です。
[配列]
配列は、必ず要素数を指定する必要があります。
加えて、指定された要素数は一切変えることができません。
[コレクション]
一方コレクションは、要素数を指定しません。
要素数は自由に増減することができます。
removeメソッドの書き方です。
コレクション名.remove(添え字)
ex) list.remove(1)
removeメソッドの引数には、削除したいインスタンスの添え字を渡します。
※添え字は0から始まることに注意!
removeメソッドの前には、コレクションの変数名を指定します。
どのコレクションの何番目のインスタンスを削除したい
と指定するわけですね。
これにより、removeメソッドは、コレクションと添え字から、指定のインスタンスを探し出し、
該当コレクションから削除してくれます。
一番簡単な使い方は引数に添え字(index)を渡すことです
removeメソッドの引数には、様々な値を渡すことができます。
削除したいインスタンスごと渡すこともできますし、indexOf()で削除したいものを
探すという方法もあります。
しかし一番カンタンかつ使いやすいのが、添え字を引数に渡すことです。
削除したいインスタンスがコレクションの中の何番目かを指定する必要がありますが、
for文と組み合わせるととても簡単にわかりやすく表現することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class Main { public static void main(String[] args) { ArrayList<String> list2 = new ArrayList<String>(); list2.add("aaa"); list2.add("bbb"); list2.add("aaa"); list2.add("ddd"); list2.add("eee"); //list2コレクションの中から、"aaa"だけを削除したい //17行目: list2からi番目のインスタンスを取得し、"aaa"と比較する //18行目: "aaa"と合致したらi番目のインスタンスを削除する for (int i = 0; i < list2.size(); i++) { if (list2.get(i).equals("aaa")) { list2.remove(i); } } for (String str : list2) { System.out.println(str); } } } |
remove の注意点!(添え字がずれます)
ここでremoveメソッドを使うときの最大の注意点です。
・添え字が自動で変わる
これは注意しなくてはいけません。
remove はインスタンスを削除してくれますが、それだけではありません。
コレクションの中身を1つ前に詰める
という特徴があります。
削除後、インスタンスを前に詰めるまでが、remove の働きです。
図にするとこのようになります。
removeを使うときは、添え字・要素数の変化に十分注意しましょう!
これを踏まえて、例プログラムです。
このプログラムでは、コレクションの要素全てを削除できません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public class Main{ public static void main(String[] args) { ArrayList<String> list3 = new ArrayList<>(); list3.add("aaa"); list3.add("aaa"); list3.add("aaa"); list3.add("aaa"); list3.add("aaa"); // list2コレクションの中から、"aaa"だけを削除したいが // 要素数がずれてしまうため、全てのインスタンスをチェックできない for (int i = 0; i < list3.size(); i++) { if (list3.get(i).equals("aaa")) { list3.remove(i); } } for (String str : list3) { System.out.println(str); } } } 【出力結果】 aaa aaa |
for 文に注目です。
i = 0 の1周目。
list.get(0) は “aaa” のため、removeが実行されます。
その結果、添え字 [1] の場所に合った”aaa”は、添え字 [0] に変化します。
それ以降の”aaa”も、添え字が一つずつ前にズレます。
i = 1 の2週目。
list.get(1)は ”aaa” です。
しかしこの “aaa” は本来、添え字 [2] の場所にあった ”aaa” です。
本来添え字 [1] の場所にあった “aaa” はチェックされずにスルーされてしまいます。
コレクションを0から順にみると、添え字のズレが原因で
本来削除したいはずのインスタンスがコレクションに残ってしまう現象が発生します。
この現象を解決するのが下記プログラムです。
コレクションを後ろから見ています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class Main3 { public static void main(String[] args) { ArrayList<String> list3 = new ArrayList<>(); list3.add("aaa"); list3.add("aaa"); list3.add("aaa"); list3.add("aaa"); list3.add("aaa"); // コレクションを後ろから見る。(これから見る要素の添え字は変わらない。) for (int i = list3.size() - 1; i >= 0; i--) { if (list3.get(i).equals("aaa")) { list3.remove(i); } } for (String str : list3) { System.out.println(str); } } } |
for 文に注目です。
i = 4 の1周目。
list.get(4) は “aaa” のため、removeメソッドが実行されます。
removeメソッドは、削除実行後、インスタンスを前に詰める働きがありますが、
後ろから見ると、全く変化はありません。
i = 3 の2週目。
list.get(3) は “aaa” のため、removeメソッドが実行されます。
removeメソッドは、削除実行後、インスタンスを前に詰める働きがありますが、
後ろから見ると、全く変化はありません。
このように、後ろからみることで、削除後自動で前詰めする働きを
回避することができます!
コレクションのすべての要素をチェックして、
条件に該当する要素をremoveしたいときは
コレクションを後ろからチェックしましょう!!
インスタンスを削除したければremove()を使いましょう!
removeメソッドの役割を確認できましたでしょうか。
コレクションを後ろからチェックすることは、
今後も頻繁に出てくるかと思います。
それに加えもう一つ。
removeは、拡張for文の中では扱えません。
拡張for文の機能とバッティングして、エラーが出てしまいます。
何かと利用するには気を使わないといけませんが、
インスタンスを削除するときには必須のメソッドですので、
マスターしましょう!
ご覧いただきありがとうございました。
コメント