インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

これは、最近のインタビューで尋ねられたインタビューの質問です。このブログ投稿では、この質問を要約して共有しています。

1.初心者が犯すよくある間違い

たぶん、多くの初心者(私を含む)は最初に次のように書くことを考えました:

public static void main(String[] args) {
    List<String> platformList = new ArrayList<>();
    platformList.add("博客园");
    platformList.add("CSDN");
    platformList.add("掘金");
    for (String platform : platformList) {
        if (platform.equals("博客园")) {
            platformList.remove(platform);
        }    }    System.out.println(platformList);
}

それから私は自信を持ってそれを実行しましたが、java.util.ConcurrentModificationExceptionがスローされたことがわかりました。

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

なぜこれがそうなのかと不思議に思っていますか?

以下に示すように、最初に上記のコードによって生成されたバイトコードを見てみましょう。

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

foreachループが実際に実行されると、実際には反復子が使用され、使用されるコアメソッドはhasnext()およびnext()であることがわかります。

次に、ArrayListクラスのIteratorがどのように実装されているかを見てみましょう。

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

次の要素を取得するためにnext()メソッドが呼び出されると、コードの最初の行はcheckForComodification();を呼び出すことであり、このメソッドのコアロジックは、2つの変数modCountとexpectedModCountの値を比較することです。

上記の例では、最初にmodCountとexpectedModCountの値が両方とも3であるため、要素「Blog Garden」を初めて取得することは問題ありませんが、次のコード行が実行されるときは問題ありません。

platformList.remove(platform);

modCountの値が4に変更されます。

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

したがって、2回目に要素を取得すると、modCountとexpectedModCountの値が等しくないため、java.util.ConcurrentModificationExceptionがスローされます。

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

foreachを使用して達成することはできないので、どうすればそれを達成できますか?

主に次の3つの方法があります。

  • イテレータのremove()メソッドを使用する
  • forループを使用して正の順序でトラバースする
  • forループを使用して逆順でトラバースします

次に一つずつ説明します。

2.イテレーターのremove()メソッドを使用します

Iteratorを使用したremove()メソッドの実装は次のとおりです。

public static void main(String[] args) {
    List<String> platformList = new ArrayList<>();
    platformList.add("博客园");
    platformList.add("CSDN");
    platformList.add("掘金");
    Iterator<String> iterator = platformList.iterator();    while (iterator.hasNext()) {
        String platform = iterator.next();        if (platform.equals("博客园")) {
            iterator.remove();
        }    }    System.out.println(platformList);
}

出力は次のとおりです。

[CSDN, 掘金]

iterator.remove();を使用する理由

そのソースコードを見てみましょう:

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

要素が削除されるたびに、modCountの値がexpectedModCountに再割り当てされるため、2つの変数が等しくなり、java.util.ConcurrentModificationExceptionがトリガーされないことがわかります。インタビューの詳細については、公式アカウントのアマチュアグラスに注意してください。

3. forループを使用して正の順序でトラバースする

forループを使用した正の順序の走査の実装は次のとおりです。

public static void main(String[] args) {
    List<String> platformList = new ArrayList<>();
    platformList.add("博客园");
    platformList.add("CSDN");
    platformList.add("掘金");
    for (int i = 0; i < platformList.size(); i++) {
        String item = platformList.get(i);
        if (item.equals("博客园")) {
            platformList.remove(i);
            i = i - 1;
        }    }    System.out.println(platformList);
}

この実装方法は理解が容易です。つまり、配列の添え字を使用して削除しますが、要素を削除した後、添え字の値を変更する必要があることに注意してください。

i = i - 1;

下付き文字の値を修正するのはなぜですか?

最初の要素のインデックスは次のようになっているためです:

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

最初のサイクルで要素「ブログガーデン」を削除した後、要素の添え字は次のようになります。

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

2番目のループでは、iの値は1です。つまり、要素「Nuggets」が取得されます。これにより、要素「CSDN」がスキップされてチェックされるため、要素を削除した後、上記の添え字を変更する必要があります。コードでi = i-1;の目的。その他のインタビューの質問については、WeChatサブスクリプション番号「Amateur Grass」に従って、インタビューに返信してください。

4. forループを使用して逆順でトラバースします

forループを使用した逆トラバーサルの実装は次のとおりです。

public static void main(String[] args) {
    List<String> platformList = new ArrayList<>();
    platformList.add("博客园");
    platformList.add("CSDN");
    platformList.add("掘金");
    for (int i = platformList.size() - 1; i >= 0; i--) {
        String item = platformList.get(i);
        if (item.equals("掘金")) {
            platformList.remove(i);
        }    }    System.out.println(platformList);
}

この実装は、forループを使用して正の順序でトラバースするのと似ていますが、最初の要素の添え字は次のようになるため、添え字を変更する必要はありません。

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

最初のサイクルで要素「ナゲット」を削除した後、要素の添え字は次のようになります。

インタビュアーは尋ねました:リストを削除しながらどのようにトラバースするのですか?

 

2番目のループでは、iの値は1です。つまり、要素「CSDN」が取得されるため、要素がスキップされることはないため、添え字を変更する必要はありません。

おすすめ

転載: blog.csdn.net/qq_45401061/article/details/108721426