検索

ホームページ  >  に質問  >  本文

java - 遍历list的时候为什么不能修改呢?

求一个明确的解答,通俗易懂的哈

巴扎黑巴扎黑2770日前936

全員に返信(4)返信します

  • 大家讲道理

    大家讲道理2017-04-17 14:59:37

    特定の言語の実装は異なります。言語に依存しない点がいくつかあります

    • 走査中に配列にデータを追加すると、不完全な走査 (新しいメンバーの長さが変化するため) または無限ループ (常に新しいメンバーが入ってくるため) が発生します

    • トラバーサル中にデータが削除された場合、配列アクセスは範囲外になります (長さが短くなり、ポインターが空としてマークされた領域を指すため)

    • @Terry_139061 の答えとして、トラバーサル中にノード自体のデータを変更するだけであれば、一般的には安全です (もちろん、特定のシナリオによって異なります)

    返事
    0
  • PHP中文网

    PHP中文网2017-04-17 14:59:37

    問題の説明はあまり正確ではありません。タグは javalisp です。私は少しラケットのコードを書いただけなので、次のデフォルトの変更は の追加/削除操作です。リスト

    • まず第一に、Java にはさまざまな種類のリストがあります:

      リーリー

      このうち、CopyOnWriteArrayList は、読み取りと書き込みを分離することでエラーが発生しません。 Wiki の Copy-on-write を参照してください。

    • 2 番目に、Java にはいくつかのトラバーサル メソッドがあります。

      リーリー

      • は、アクセスするオブジェクトを削除するか、配列が範囲外になるか、追加を続けて無限シーケンスを生成する場合を除き、for ループ内で変更しても問題ありません。for

      • の場合、 iterator.remove() を使用しても問題はありません。 iterator.remove() は iterator を設定するためです。 リーリー

        このようにして、iterator.next() はトラバースして実行した後に例外をスローしません

        リーリー

      • は本質的に暗黙的な反復子です (javap -c を使用してバイトコードを比較できます)。expectedModCount はリセットされないため、list.remove() を使用するときは、iterator.next( ) 教えてくれます foreachConcurrentModificationException

    • 最後に、ここには特別なことがあります。リストの最後から 2 番目の値を削除すると、hasNext() がトリガーされると、結果は false となり、ループを終了し、next( の実行は続行されません。 )、エラーは報告されません。

      リーリー

    追記: 使用される JDK は java-8-openjdk-amd64 です

    返事
    0
  • 天蓬老师

    天蓬老师2017-04-17 14:59:37

    これは変更できます。次のプログラムは 3 aaaaa

    を出力します。 リーリー

    トラバースにどのような方法を使用しましたか?分析に役立つようにコードを投稿してください。

    返事
    0
  • 高洛峰

    高洛峰2017-04-17 14:59:37

    Java の観点からこの質問に答えると、Iterator パターンはコレクション クラスを横断するための標準的なアクセス方法です。さまざまなタイプのコレクション クラスからアクセス ロジックを抽象化できるため、コレクションの内部構造がクライアントに公開されるのを回避できます。
    たとえば、Iterator が使用されていない場合、配列を反復処理するにはインデックスを使用します。

    リーリー
    • クライアントは、コレクションの内部構造を事前に知っておく必要があります。アクセス コードとコレクション自体は密接に結合されており、アクセス ロジックをコレクション クラスとクライアント コードから分離することはできません。トラバーサル メソッドの場合、クライアント コードは再利用できません。

    • さらに恐ろしいのは、将来 ArrayList を LinkedList に置き換える必要がある場合、元のクライアント コードを完全に書き直す必要があることです。上記の問題を解決するために、Iterator モードは常に同じロジックを使用してコレクションを走査します。

      リーリー

      - その秘密は、クライアント自体がコレクションを走査するための「ポインター」を維持しないことです。すべての内部状態 (現在の要素の位置、次の要素があるかどうかなど) はイテレーターによって維持され、このイテレーターはファクトリ メソッドを通じてコレクション クラスによって生成されるため、コレクション全体を走査する方法がわかります。クライアントはコレクション クラスを直接処理することはなく、常に Iterator を制御し、「forward」、「backward」、および「get the current element」コマンドを送信して、コレクション全体を間接的に走査します。

    • Iterator を使用してコレクション要素を反復処理する場合、collection はコレクション要素自体を反復変数に渡しませんが、コレクション要素の値を反復変数に渡します。したがって、反復変数の値を変更しても、コレクション要素自体の値は変更されません。イテレータ イテレータはオブジェクトを保存せず、Collection オブジェクトに添付され、コレクションを走査するためにのみ使用されます。イテレータ イテレータは、フェールファスト メカニズムを使用します。反復プロセス中にコレクションが変更されたことが検出されると、プログラムは変更された結果を表示する代わりに、ただちに java.util.ConcurrentModificationException をスローします。これにより、リソースの共有によって引き起こされる潜在的な問題が回避されます。

    リーリー
    • { str = "hello" } ステートメントを実行しても、 iterator.remove() を実行すると、現在の反復オブジェクトが削除され、java が報告されます。 .util.ConcurrentModificationException は、コレクションの要素が変更されたことを検出するためです。

      返事
      0
  • キャンセル返事