Javaで配列から要素を削除する高速(かつ見栄えの良い)方法はないでしょうか?
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);
}
注意:これはテストされていません。 エラーチェックは演習として読者に任されています(inputまたはdeleteMeのいずれかがnullの場合、IllegalArgumentExceptionを投げます。nullリスト入力の空のリストは意味がありません。 nullを削除する配列から文字列を削除することは理にかなっているかもしれませんが、私もそれを演習として残します。現在、deleteMeがnullの場合、deleteMeで等号を呼び出そうとすると、NPEがスローされます。)。
ここで行った選択:
LinkedListを使用しました。 反復も同様に高速である必要があり、サイズ変更を回避したり、多くの要素を削除してしまう場合は、リストを割り当てすぎたりします。 配列リストを使用して、初期サイズを入力の長さに設定できます。 それはおそらく大きな違いはありません。
最良の選択はコレクションを使用することですが、それが何らかの理由で出ている場合は、[arraycopy
](https://docs.oracle.com/javase/7/docs/api/java/lang/Systemを使用します。 html#arraycopy(java.lang.Object、%20int、%20java.lang.Object、%20). これを使用して、わずかに異なるオフセットで同じ配列から同じ配列にコピーできます。
例:
public void removeElement(Object[] arr, int removedIdx) {
System.arraycopy(arr, removedIdx + 1, arr, removedIdx, arr.length - 1 - removedIdx);
}
---。
コメントに応じて編集:
これは別の良い方法ではありません。これが実際に受け入れられる唯一の方法です。この機能を可能にするツール(Java.ArrayListやApache utilsなど)は、この方法をカバーの下で使用します。 また、あなたは本当にArrayList(または中央からたくさん削除する場合はリンクリスト)を使用する必要があるため、宿題として行わない限り、これは問題にはなりません。
コレクションを割り当てる(新しい配列を作成する)には、要素を削除し(コレクションは配列コピーを使用して行います)、次にtoArrayを呼び出します(2番目の新しい配列を作成します)。削除するたびに、最適化ではない問題になります。 、それは犯罪的に悪いプログラミングです。
たとえば、100mbのラムを占める配列があるとします。 次に、それを反復して20の要素を削除します。
試してみてください。..
それほど大きくなることはない、または一度に多くを削除する場合は別の方法でコーディングすると思いますが、誰かがそのような仮定を行った非常に多くのコードを修正しました。
格好いい解決策は、そもそも配列の代わりにリストを使うことでしょう。
List.remove(index)
配列を使う必要がある場合は、System.arraycopy
を2回呼び出すと最速になる可能性が高いです。
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統合のいずれかに配列を使用します。 後で、それらをコレクションに変換して、ビジネスロジックに渡しても問題ありません。
低レベルのパフォーマンスのものについては、通常、ループなどのために迅速かつ汚れた必須の混合によってすでに難読化されています。 その場合、コレクションとアレイの間を行き来することは面倒で、読み取ることができず、リソース集約的でさえあります。
ちなみに、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を使用して、「見栄えの良い方法」で削除できます。 Arraysで多くの操作(削除、検索、追加、包含など)を実装します。 見てください。 それは私の人生をよりシンプルにしました。
配列の長さを変更することはできませんが、新しい値をコピーしてインデックスを保持する値を変更し、既存のインデックス番号に保存できます。 1 =マイク、2 =ジェフ// 10 =ジョージ11は1つの上書きマイクになります。 .
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;
わかりました、たくさん。 今私はこのようなsthを使用します:
public static String[] removeElements(String[] input, String deleteMe) {
if (input != null) {
List<String> list = new ArrayList<String>(Arrays.asList(input));
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(deleteMe)) {
list.remove(i);
}
}
return list.toArray(new String[0]);
} else {
return new String[0];
}
}