web-dev-qa-db-ja.com

配列からアイテムを削除し、配列を縮小

配列からアイテムを削除し、配列のサイズを小さくするにはどうすればよいですか?同様に、別のアイテムを追加する必要がある場合、どうすれば容量を増やすことができますか?

33
Joe

Java配列のサイズは、割り当てたときに固定され、変更できません。

  • 既存の配列を「拡大」または「縮小」する場合は、適切なサイズの新しい配列を割り当てて、配列要素をコピーする必要があります。例えばSystem.arraycopy(...)またはArrays.copyOf(...)を使用します。コピーループも同様に機能しますが、少し不格好に見えますが... IMO。

  • 配列からアイテムを「削除」したい場合(本当の意味で... nullで置き換えるだけではありません)、新しい小さな配列を割り当て、必要な要素にコピーする必要があります保持する。

サードパーティライブラリの形式の代替手段(Apache Commons ArrayUtilsなど)がありますが、ライブラリの依存関係just5〜10行のコードで自分で実装できるメソッドのために。


それはより良いです(すなわち、よりシンプルで...多くの場合、より効率的です1)配列の代わりにListクラスを使用します。これにより、(少なくとも)バッキングストレージの拡張が処理されます。また、リスト内のどこにでも要素の挿入と削除を処理する操作があります。

たとえば、ArrayListクラスはバッキングとして配列を使用し、必要に応じて配列を自動的に拡大します。バッキング配列のサイズは自動的に縮小されませんが、trimToSize()メソッドを使用してこれを行うように指示できます。例えば.

ArrayList l = ...
l.remove(21);
l.trimToSize();  // Only do this if you really have to.

1-ArrayListは、バッキング配列を大きくする必要があるときに単純な「サイズを2倍にする」戦略を使用するため、「多くの場合により効率的」だと言います。つまり、リストに繰り返し追加してリストを拡大すると、各要素は平均して1回余分にコピーされます。対照的に、配列でこれを行った場合、各配列要素を平均でN/2回近くコピーすることになります。

25
Stephen C

配列自体のサイズを変更することはできませんが、次のようなユーティリティ関数を使用して、新しい配列を作成し、古い配列から新しい配列に要素を効率的にコピーできます。

public static int[] removeElement(int[] original, int element){
    int[] n = new int[original.length - 1];
    System.arraycopy(original, 0, n, 0, element );
    System.arraycopy(original, element+1, n, element, original.length - element-1);
    return n;
}

ただし、より良い方法は、ArrayList(または同様のリスト構造)を使用してデータを保存し、そのメソッドを使用して必要に応じて要素を削除することです。

17
Mark Elliot

Org.Apache.commons.langのArrayUtils.removeElement(Object[],Object)を使用するのが、これを行う最も簡単な方法です。

int[] numbers = {1,2,3,4,5,6,7};
//removing number 1
numbers =(int[])ArrayUtils.removeElement(numbers, 1);
12
azraelAT

配列には作成時に割り当てられる固定サイズがあるため、唯一のオプションは、削除する要素なしで新しい配列を作成することです。

削除する要素が最後の配列項目である場合、これは_Arrays.copy_を使用して簡単に実装できます。

_int a[] = { 1, 2, 3};
a = Arrays.copyOf(a, 2);
_

上記のコードを実行すると、aは1、2のみを含む新しい配列を指すようになります。

それ以外の場合、削除する要素が最後の要素でない場合は、サイズ1で新しい配列を作成し、削除するものを除くすべての項目をそこにコピーする必要があります。

上記のアプローチは効率的ではありません。メモリ内のアイテムの可変リストを管理する必要がある場合は、リストを使用することをお勧めします。具体的には、LinkedListは、O(1)のリストから項目を削除します(理論的に可能な限り高速)。

4
Guy

この関数、またはクラスを作成しました。私はちょっと新しいですが、私の友人もこれを必要としていたので、私はこれを作成しました:

public String[] name(int index, String[] z ){
    if(index > z.length){
        return z;
    } else {
        String[] returnThis = new String[z.length - 1];
        int newIndex = 0;
        for(int i = 0; i < z.length; i++){
            if(i != index){
                returnThis[newIndex] = z[i];
                newIndex++;
            }
        }
        return returnThis; 
    }
}

かなり面白かったので、ここに投稿すると思いました。

2
Engineer
object[] newarray = new object[oldarray.Length-1];

for(int x=0; x < array.Length; x++)
{
  if(!(array[x] == value_of_array_to_delete))
  // if(!(x == array_index_to_delete))
   {
     newarray[x] = oldarray[x];
   }
}

配列を作成した後にサイズを縮小する方法はありませんが、コンテンツをより小さいサイズの別の配列にコピーできます。

1
Mike

配列のサイズは固定されており、作成後にサイズを変更することはできません。 nullに設定することにより、既存のアイテムを削除できます。

_objects[4] = null;
_

ただし、そのスロット全体をアレイから削除して、サイズを1減らすことはできません。

動的なサイズの配列が必要な場合は、ArrayListを使用できます。これを使用すると、 add() および remove() オブジェクトを使用でき、必要に応じて拡大および縮小します。

0
BoltClock

system.arraycopyメソッドを使用せずに、次のようにして配列から要素を削除できます

    int i = 0;
    int x = 0;
    while(i < oldArray.length){
        if(oldArray[i] == 3)i++;

        intArray[x] = oldArray[i];
        i++;
        x++;
    }

ここで、3は削除する値です。

0
tkolleh