web-dev-qa-db-ja.com

どのように配列を反復処理して要素を削除しますか?

配列があり、繰り返し処理できます。配列のサイズを変更することは不可能です。しかし、配列に必要のない特定の要素をどのように取り出すのですか?

例:ユーザーが特定の要素を削除することを選択した場合、これをコードに書き出すにはどうすればよいですか?

3
Elijah Hampton

Javaコレクションフレームワーク は、参照する必要があるものです。配列に似ていないタイプもいくつかありますが(SetとMap)、頻繁に使用することがわかります。コレクションにはさまざまなタイプがあり、特定のタイプの操作については、いくつかのコレクションが他のコレクションよりも優れています。

クラシック配列

まず、コレクションフレームワークではではないものです。アレイ。 ArrayListではなく、古典的なint[]です。配列の利点は、メモリが何であるかに密接にマッピングされることです。 foo[42]は検索することです。固定数の項目を提供する多くのシステムレベルの呼び出しは配列であり、知っておくと役に立ちます。 "1,2,3".split(",")は、たとえば配列を返します。

配列の問題は、それらがそれほど柔軟ではないことです。すでに最大容量になっている配列の最後に要素を追加するということは、新しい大きな配列を割り当ててから、System.arraycopy()javadoc )を実行してすべての要素をコピーすることを意味しますあるアレイを別のアレイに適時に。

リストから要素をremoveするには、要素を削除してから、リストの残りの部分をウォークして、すべての要素を再び感染させる必要があります。リストからfoo[4]を削除する場合は、リストの最後にfoo[4] = foo[5]foo[5] = foo[6]を割り当てます。手でやらなければならないのなら。上記のSystem.arraycopyを使用して、適切な引数のセットを指定して実行することもできます。何かのようなもの:

System.arraycopy(foo,5,foo,4,foo.length - 4);

私はそれが間違っているかもしれませんが、それは一般的な考えです。アレイをそれ自体にコピーします。それは動作するはずです

Src引数とdest引数が同じ配列オブジェクトを参照している場合、srcPosからsrcPos + length-1の位置にあるコンポーネントが最初に長さコンポーネントを持つ一時配列にコピーされ、次に一時配列の内容がデスティネーション配列の位置destPosからdestPos + length-1にコピーされます。

リスト

ご覧のとおり、配列は扱いにくいです。すべて手作業で行う必要があります。知っておくと良いですが、練習するのは大変です。これを簡単にするために一般的に使用されている2つのリストがあります。ほとんどの場合、リストは配列のようにlookです。

List<Integer> foo = ...;
foo.get(4);
foo.remove(5);

それらのメソッドを呼び出しますが、配列を介した直接アクセスではなく、メソッド呼び出しを介して4番目の要素をフェッチしています。 foo.remove(5)を参照してください。それでおしまい。完了です。リストから要素を削除して削除しました。覚えやすくなります。

配列リスト

ArrayListはArrayによってサポートされています。つまり、foo.get(4)を実行すると高速に実行されますが、foo.add(42, foo.size()+1)は、新しいリストを割り当てるためにすべての移動を行わなければならないため、遅くなる可能性があります(そうです、リストはサイズより長くてもかまいませんが、実際のリストと同じサイズであると想定します)。

すべてのシャッフルを行う方法を覚えておく必要がある代わりに、あなたのためにあなたの仕事をするための素晴らしい方法があります。それが完了していないことを意味するわけではありません(作業はまだインターフェースの背後で行われています)が、心配する必要はありません。

つまり、ArrayListは次のようなものです。

  • 高速取得(O(1))
  • 削除と挿入が遅い(O(長さ))
  • いっぱいになると追加が遅くなる(O(長さ))

LinkedList

何らかの理由で、全員のgotoリストの実装はArrayListです。理由はわかりません。多くの場合、リストを操作しているとき、LinkedListがより適切なものです。あなたは最後に物事を追加し続けます。めったにnが欲しい番目 素子。あなたはそれらを反復したいだけです。

これがLinkedListのメリットです。削除と追加は高速で、そのイテレータはArrayListと同じくらい高速です。 foo.get(400)が必要な場合は、ArrayList実装よりも少し遅くなります。

LinkedListもDequeですが、人々はそれを忘れています。これにより、LinkedListにダブルエンドキューとしてアクセスできます(スタックまたはキューの実装に最適)。

したがって、追加と反復を行うだけの場合は、LinkedListが適しています。

  • 取得が遅い(O(index))
  • 高速追加(O(1))
  • 削除と挿入が遅い(O(index))

O(index)賞のビットが少しあることに注意してください。これは、(最後からまたは最初から)どちらの方法で到達するのが速いかに応じてインデックスを作成します。したがって、LinkedListが100の長さで、get(10)の場合、最初から開始されます。get(90)を要求した場合、最後から開始されます。したがって、get(index)はget(length/2)以下ですが、それだけです。 Big Oを見るときに重要ではない要素だけです。

6
user40980

配列を使用してこれを行う必要がある場合は、次のことを行う必要があります。

  • 削除された要素をカバーするために、要素が1つ下に削除された後の配列のすべての要素をコピーします。

  • 配列のサイズを1要素だけ小さくします。

要素を1つ下にコピーするには、自分でループを作成するか、System.arraycopy( src, srcPos, dest, destPos, length)を呼び出します。

配列のサイズ変更は次のように行うことができます:myArray = Arrays.copyOf( myArray, newCapacity )

そうは言っても、配列の長さを操作する必要がある場合は、配列を使用する代わりにArrayListを使用してください。このホイールはすでに発明されています。

1
Mike Nakis

参照タイプの配列の場合、各セルの内容はデフォルトでnullになります。セルに実際の値を配置した場合、それをnullで置き換えることにより、効果的に「削除」できます。コードがnullの値をチェックしている限り、nullで置き換えると削除としてカウントできます。しかし、これは配列の非効率的な使用です。その主な利点は、数が変化しないインデックス付きの値にアクセスする速度です。 「コレクション」に特定の値が含まれている場合と含まれていない場合は、マップまたはリストが適しています。

プリミティブの配列(intbyteなど)の場合、コンテンツを削除することはできません。 default値(数値型の場合は、ブール値の場合はfalse)を挿入できますが、おそらく役に立たないでしょう。最善の方法は、それ以外のすべての要素を新しい配列にコピーすることです。あなたができることまたnullではないすべてのものをコピーすることによって参照型に対して行うことができます。

重要な質問はこれです:

  1. 特定の配列インデックスに意味のある値が含まれているかどうかを知りたいですか?

  2. または現在配列にあるすべての値に単に興味がありますか?

答えが1の場合、プリミティブ型の答えはnoです。 参照タイプの場合、それらをnullで置き換えることができますが、実際には、キーを削除できるため、マップの方が優れています。

答えが2の場合、他のすべてのセルを新しい配列にコピーできます。

どっち?

0
itsbruce