Javaで配列から要素を削除するための高速な(そして見栄えの良い)方法はありますか?
15 に答える
commons lang の ArrayUtils を使用できます。
array = ArrayUtils.removeElement(array, element)
あなたの質問はあまり明確ではありません。あなた自身の答えから、あなたがやろうとしていることをよりよく知ることができます:
public static String[] removeElements(String[] input, String deleteMe) {
List result = new LinkedList();
for(String item : input)
if(!deleteMe.equals(item))
result.add(item);
return result.toArray(input);
}
注意: これはテストされていません。エラー チェックは、読者の演習として残されています (またはIllegalArgumentException
いずれinput
かdeleteMe
が null の場合はスローします。null リスト入力の空のリストは意味がありません。配列から null 文字列を削除することは意味があるかもしれませんが、それはそのままにしておきます演習としても; 現在、is nullの場合NPE
に equals を呼び出そうとすると、 がスローされます。)deleteMe
deleteMe
ここで行った選択:
を使用しましたLinkedList
。反復は同じくらい高速である必要があり、多くの要素を削除してしまう場合は、サイズ変更や大きすぎるリストの割り当てを避けます。を使用してArrayList
、初期サイズを入力の長さに設定できます。それはおそらく大きな違いはありません。
最良の選択はコレクションを使用することですが、何らかの理由でコレクションが使用できない場合は、arraycopy
. これを使用して、わずかに異なるオフセットで同じ配列との間でコピーできます。
例えば:
public void removeElement(Object[] arr, int removedIdx) {
System.arraycopy(arr, removedIdx + 1, arr, removedIdx, arr.length - 1 - removedIdx);
}
コメントに応じて編集:
これは別の良い方法ではありません。これが実際に受け入れられる唯一の方法です。この機能を使用できるツール (Java.ArrayList や apache utils など) は、この方法を内部で使用します。また、本当に ArrayList (または途中から削除する場合はリンク リスト) を使用する必要があるため、宿題として実行していない限り、これは問題にはなりません。
コレクションを割り当て (新しい配列を作成)、次に要素を削除 (コレクションは arraycopy を使用して行う) し、削除するたびに toArray を呼び出し (2 番目の新しい配列を作成)、最適化の問題ではない点に到達します。 、それは犯罪的に悪いプログラミングです。
たとえば、100MB の RAM を占有する配列があるとします。次に、それを反復して 20 個の要素を削除します。
試してみる...
それほど大きくならない、または一度に多くを削除する場合は別の方法でコーディングするだろうと想定していることは知っていますが、誰かがそのような想定をした非常に多くのコードを修正しました。
基本的な Java 配列から要素を削除することはできません。代わりに、さまざまなコレクションと ArrayList を見てください。
見栄えの良い解決策は、最初に配列の代わりにリストを使用することです。
List.remove(index)
配列を使用する必要がある場合は、 を 2 回呼び出すSystem.arraycopy
のが最も高速です。
Foo[] result = new Foo[source.length - 1];
System.arraycopy(source, 0, result, 0, index);
if (source.length != index) {
System.arraycopy(source, index + 1, result, index, source.length - index - 1);
}
(Arrays.asList
も配列を操作するのに適していますが、サポートしていないようですremove
。)
質問は、コレクション API を使用しないソリューションを求めていたと思います。配列は、パフォーマンスが重要な低レベルの詳細、または疎結合の SOA 統合のために使用されます。後はコレクションに変換してそのままビジネスロジックに渡せばOKです。
低レベルのパフォーマンスのものについては、通常、 for ループなどによる迅速かつ汚い命令的な状態混合によって既に難読化されています。その場合、コレクションと配列の間を行ったり来たりするのは面倒で、判読できず、リソースを集中的に使用することさえあります。
ところで、TopCoder さん、誰かいますか?常にそれらの配列パラメーター! そのため、アリーナにいるときにそれらを処理できるように準備してください.
以下は、問題の私の解釈と解決策です。Bill Kおよびjelovirtによって提供されたものとは機能が異なります。また、要素が配列にない場合も適切に処理します。
それが役立つことを願っています!
public char[] remove(char[] symbols, char c)
{
for (int i = 0; i < symbols.length; i++)
{
if (symbols[i] == c)
{
char[] copy = new char[symbols.length-1];
System.arraycopy(symbols, 0, copy, 0, i);
System.arraycopy(symbols, i+1, copy, i, symbols.length-i-1);
return copy;
}
}
return symbols;
}
ArrayUtils APIを使用して、「見栄えの良い方法」で削除できます。配列に対して多くの操作(削除、検索、追加、含むなど)を実装します。
見てください。それは私の人生をよりシンプルにしました。
配列の長さは変更できませんが、新しい値をコピーして既存のインデックス番号に格納することで、インデックスが保持する値を変更できます。1=mike , 2=jeff // 10 = george 11 は 1 の上書き mike になります。
Object[] array = new Object[10];
int count = -1;
public void myFunction(String string) {
count++;
if(count == array.length) {
count = 0; // overwrite first
}
array[count] = string;
}
Bill Kとdadinnによって書かれたものには、さらにいくつかの前提条件が必要です
Object[] newArray = new Object[src.length - 1];
if (i > 0){
System.arraycopy(src, 0, newArray, 0, i);
}
if (newArray.length > i){
System.arraycopy(src, i + 1, newArray, i, newArray.length - i);
}
return newArray;
Javaコレクション/Javaコモンズコレクションをご利用いただければ幸いです!
java.util.ArrayList を使用すると、次のようなことができます。
yourArrayList.remove(someObject);
yourArrayList.add(someObject);
要素を削除せずに、元の配列を別の配列にコピーします。
これを行う簡単な方法は、List、Set... を使用し、remove() メソッドを使用することです。
配列のサイズを小さくする必要がない場合は、削除するアイテムを最後のアイテムと交換します。
次を使用しArrayList
ます。
alist.remove(1); //removes the element at position 1
もちろん、別の配列を作成してください:)