0
0

removeIfの中身

Posted at

 JavaでMapから条件付きで要素を削除する場合に、for文ではうまくいかない。これは、collectionの構造がiteration中に変更されて、ConcurrentModificationExceptionがthrowされたことによるものらしい。
代替手段として、removeIfメソッドを用いると想定通りにプログラムが動いた。ソースを見ると比較的スクリプトが少なく簡単に読めそうなので、詳細を確認しよう。

public interface Collection<E> extends Iterable<E> {
// 省略
   default boolean removeIf(Predicate<? super E> filter) {
       Objects.requireNonNull(filter); //1
       boolean removed = false; //2
       final Iterator<E> each = iterator(); //3
       while (each.hasNext()) { //4
           if (filter.test(each.next())) { //5
               each.remove(); //6
               removed = true; //7
           }
       }
       return removed; //1
   }

   /**
    * Retains only the elements in this collection that are contained in the
    * specified collection (optional operation).  In other words, removes from
    * this collection all of its elements that are not contained in the
    * specified collection.
    *
    * @param c collection containing elements to be retained in this collection
    * @return {@code true} if this collection changed as a result of the call
    * @throws UnsupportedOperationException if the {@code retainAll} operation
    *         is not supported by this collection
    * @throws ClassCastException if the types of one or more elements
    *         in this collection are incompatible with the specified
    *         collection
    *         ({@linkplain Collection##optional-restrictions optional})
    * @throws NullPointerException if this collection contains one or more
    *         null elements and the specified collection does not permit null
    *         elements
    *         ({@linkplain Collection##optional-restrictions optional})
    *         or if the specified collection is null
    * @see #remove(Object)
    * @see #contains(Object)
    */      

①渡されたPredicateに対してのnullチェック
②最終的に削除が行われたかどうかの返り値の初期化
③削除をするためのcollectionのiteratorを取得。このeachに対して繰り返しの削除行為を実施する。
④iteratorに次の要素があるかを確認して、ある場合はループが継続
⑤条件に基づいてbooleanを決定
⑥該当する条件のものはiteratorから削除
⑦⑧1つでも削除したものがある場合は最終的にtrueを返す

 重要なのはcollectionとiterator(iterable)の違いということのようだ。

  • iterable:その名の通り、コレクションの要素を反復処理するためのインターフェースであり、特にfor-each(enhanced for statement)の対象となる
  • collection:iterableを継承し、より多くの操作を可能としている

今回自分の中で腑に落ちていない点は以下の通り、今後勉強する中で解決することを望む。

  1. iteratorの変更がどうやって元のcollectionに反映されるのか
  2. removeIfの返値booleanはどこで使われているか
  3. nextまわりは記載がかなり省略されている感じがして肌に合わない
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0