そんなループでやってみます
// ArrayList tourists
for (Tourist t : tourists) {
if (t != null) {
t.setId(idForm);
}
}
しかし、それは良くありません。誰かが私にもっと良い解決策を提案できますか?
より適切な決定を行うためのいくつかの有用なベンチマーク:
そんなループでやってみます
// ArrayList tourists
for (Tourist t : tourists) {
if (t != null) {
t.setId(idForm);
}
}
しかし、それは良くありません。誰かが私にもっと良い解決策を提案できますか?
より適切な決定を行うためのいくつかの有用なベンチマーク:
回答:
試してください:
tourists.removeAll(Collections.singleton(null));
Java APIをお読みください。コードはjava.lang.UnsupportedOperationException
不変のリスト(で作成されたものなどArrays.asList
)をスローします。詳細については、この回答を参照してください。
List.removeAll()
はn ^ 2です。ただ言って。
O(n)
との両方ArrayList
で私にはかなり見えますLinkedList
。
2015年現在、これが最良の方法です(Java 8)。
tourists.removeIf(Objects::isNull);
注:このコードはjava.lang.UnsupportedOperationException
、不変リストを含む固定サイズのリスト(Arrays.asListで作成されたものなど)に対してスローされます。
removeIf
はより高速ですが、それは推測です。
Arrays.asList
は不変ではありません。固定サイズです。
list.removeAll(Collections.singleton(null));
それは意志例外UnsupportedExceptionを、それはあなたを与えるので、あなたはは、Arrays.asListにそれを使用する場合は不変、それを修正することはできませんので、コピーを。コードの下を参照してください。可変コピーを作成し、例外をスローしません。
public static String[] clean(final String[] v) {
List<String> list = new ArrayList<String>(Arrays.asList(v));
list.removeAll(Collections.singleton(null));
return list.toArray(new String[list.size()]);
}
効率的ではないが短い
while(tourists.remove(null));
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
if (itr.next() == null) { itr.remove(); }
}
removeAll(..null..)
です。ありがとう!
使用するJava 8より前のバージョン:
tourists.removeAll(Collections.singleton(null));
Java 8以降の使用:
tourists.removeIf(Objects::isNull);
ここでの理由は時間の複雑さです。配列の問題は、削除操作が完了するまでにO(n)時間かかる可能性があることです。本当にJavaでは、これは空のスポットを置き換えるために移動される残りの要素の配列コピーです。ここで提供される他の多くのソリューションがこの問題を引き起こします。前者は厳密にはO(n * m)です。mは1なので、これはシングルトンnullです。つまり、O(n)です。
シングルトンをすべて削除する必要があります。内部的には、読み取り位置と書き込み位置を持つbatchRemove()を実行します。そして、リストを反復します。ヌルに到達すると、読み取り位置を1だけ反復します。それらが同じ場合は通過し、異なる場合は値のコピーに沿って動き続けます。その後、最後にサイズにトリミングします。
これは内部で効果的に行われます。
public static <E> void removeNulls(ArrayList<E> list) {
int size = list.size();
int read = 0;
int write = 0;
for (; read < size; read++) {
E element = list.get(read);
if (element == null) continue;
if (read != write) list.set(write, element);
write++;
}
if (write != size) {
list.subList(write, size).clear();
}
}
明示的に確認できるのはO(n)操作です。
これまでより速くなる可能性がある唯一のことは、リストを両端から繰り返し、nullを見つけたときに、その値を最後に見つけた値と等しく設定し、その値をデクリメントすることです。そして、2つの値が一致するまで繰り返しました。順序をめちゃくちゃにしてしまいますが、設定した値の数をそのままにしておくよりも大幅に減らすことができます。これは知っておくと良い方法ですが、ここでは.set()は基本的に無料であるためあまり役に立ちませんが、そのような形の削除はベルトにとって便利なツールです。
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
if (itr.next() == null) { itr.remove(); }
}
これは十分なように思えますが、イテレータの.remove()は内部的に次を呼び出します。
ArrayList.this.remove(lastRet);
これも、削除内のO(n)操作です。速度を気にする場合は、System.arraycopy()を実行しますが、これも必要な操作ではありません。これはn ^ 2になります。
またあります:
while(tourists.remove(null));
これはO(m * n ^ 2)です。ここでは、リストを反復するだけではありません。nullに一致するたびに、リスト全体を繰り返します。次に、n。2(平均)操作を実行して、System.arraycopy()を実行して削除を実行します。文字通り、値を持つアイテムとnull値を持つアイテムの間でコレクション全体を並べ替え、短い時間で終了をトリミングできます。実際、それは壊れたものすべてに当てはまります。少なくとも理論的には、実際のsystem.arraycopyは実際にはN演算ではありません。理論的には、理論と実践は同じものです。実際にはそうではありません。
Java 8を使用するstream()
と、およびを使用してこれを行うことができますfilter()
tourists = tourists.stream().filter(t -> t != null).collect(Collectors.toList())
または
tourists = tourists.stream().filter(Objects::nonNull).collect(Collectors.toList())
詳細:Java 8-ストリーム
これは、arraylistからデフォルトのnull値を削除する簡単な方法です
tourists.removeAll(Arrays.asList(null));
それ以外の場合、文字列値「null」はarraylistから削除されます
tourists.removeAll(Arrays.asList("null"));
これをいじってみたところ、trimToSize()が機能しているようです。私はAndroidプラットフォームで作業しているため、異なる場合があります。
trimToSize
の内容は変更されませんArrayList
。これがアンドロイドで異なる場合、それはおそらくバグです。
新しいリストを生成するために、ストリームインターフェイスをストリーム操作のcollectおよびヘルパーメソッドと一緒に使用しました。
tourists.stream().filter(this::isNotNull).collect(Collectors.toList());
private <T> boolean isNotNull(final T item) {
return item != null;
}
tourists.stream().filter(s -> s != null).collect(Collectors.toList());
Java 8を使用すると、これはストリーム、並列ストリーム、removeIf
メソッドを使用してさまざまな方法で実行できます。
List<String> stringList = new ArrayList<>(Arrays.asList(null, "A", "B", null, "C", null));
List<String> listWithoutNulls1 = stringList.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList()); //[A,B,C]
List<String> listWithoutNulls2 = stringList.parallelStream()
.filter(Objects::nonNull)
.collect(Collectors.toList()); //[A,B,C]
stringList.removeIf(Objects::isNull); //[A,B,C]
並列ストリームは、利用可能なプロセッサを利用し、適切なサイズのリストのプロセスを高速化します。ストリームを使用する前にベンチマークすることを常にお勧めします。
Iterator
ますか?java-docを掘る。download.oracle.com/javase/6/docs/api/java/util/...