web-dev-qa-db-ja.com

ArrayListまたはString配列からすべてのnull要素を削除する方法は?

私はそのようなループで試します

// ArrayList tourists

for (Tourist t : tourists) {
    if (t != null) {     
        t.setId(idForm); 
    }   
}

しかし、それはニースではありません。誰も私にもっと良い解決策を提案できますか?


より良い判断を下すためのいくつかの有用なベンチマーク:

ループ中、Forループおよびイテレータパフォーマンステスト

174

試してください:

tourists.removeAll(Collections.singleton(null));

Java API を読んでください。コードは、不変リスト(Java.lang.UnsupportedOperationExceptionで作成されたものなど)に対してArrays.asListをスローします。詳細については この回答 をご覧ください。

350
Lithium

2015年現在、これが最良の方法です(Java 8):

tourists.removeIf(Objects::isNull);

注:このコードは、不変リストを含む固定サイズのリスト(Arrays.asListで作成されたものなど)に対してJava.lang.UnsupportedOperationExceptionをスローします。

99
MarcG
list.removeAll(Collections.singleton(null));

スローされますnsupportedException Arrays.asListで使用すると、変更できないためImmutableコピーが提供されるためです。以下のコードを参照してください。 Mutableコピーを作成し、例外をスローしません。

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()]);
}
45
AZ_

効率的ではないが、短い

while(tourists.remove(null));
18
Peter Lawrey

不変のデータオブジェクトを好む場合、または入力リストを破壊したくない場合は、Guavaの述語を使用できます。

ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))
18
James Kojo
 for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }
7
Mat Mannion

Objectsクラスには、nonNullとともに使用できるPredicatefilterがあります。

例えば:

tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());
3
JeffF

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-Streams

3
Jad Chahine

Java 8より前のバージョンを使用する必要があります。

tourists.removeAll(Collections.singleton(null));

Java 8以降の使用:

tourists.removeIf(Objects::isNull);

ここでの理由は、時間の複雑さです。配列の問題は、削除操作が完了するまでにO(n)時間かかる場合があることです。本当にJavaにあるのは、空のスポットを置き換えるために移動される残りの要素の配列コピーです。ここで提供されている他の多くのソリューションがこの問題を引き起こします。前者は技術的にはO(n * m)であり、mは1であるため、mは1です。したがって、O(n)

すべてのシングルトンを削除する必要があります。内部では、読み取り位置と書き込み位置を持つbatchRemove()を実行します。そして、リストを繰り返します。 nullにヒットすると、読み取り位置を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に一致するたびに、リスト全体を繰り返します。次に、削除を実行するためにSystem.arraycopy()を実行するためにn/2(平均)操作を実行します。文字通り、値を持つアイテムとnull値を持つアイテムの間でコレクション全体をソートし、短時間で終了をトリムできます。実際、それはすべての壊れたものに当てはまります。少なくとも理論的には、実際のsystem.arraycopyは実際には実際にはN操作ではありません。理論的には、理論と実践は同じものです。実際にはそうではありません。

3
Tatarize

nullからすべてのcollection値を削除する簡単な方法があります。パラメータとしてnullを含むコレクションをremoveAll()メソッドに渡す必要があります

List s1=new ArrayList();
s1.add(null);

yourCollection.removeAll(s1);
3
shiv

これはarraylistからデフォルトのnull値を削除する簡単な方法です

     tourists.removeAll(Arrays.asList(null));  

それ以外の場合、文字列値「null」はarraylistから削除します

       tourists.removeAll(Arrays.asList("null"));  
2
Jobin_vibes

ストリーム操作collectおよびヘルパーメソッドと共にストリームインターフェイスを使用して、新しいリストを生成しました。

tourists.stream().filter(this::isNotNull).collect(Collectors.toList());

private <T> boolean isNotNull(final T item) {
    return  item != null;
}
1
Mabi

同じためにイテレータを使用して、すべてのnull値を削除できます。

Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
    if(itr.next() == null){
        itr.remove();
    }
}
1
amit

私はこれをいじってみて、trimToSize()が機能しているようだとわかりました。 Androidプラットフォームで作業しているので、異なる場合があります。

1
theblitz

@Lithiumの回答に似ていますが、「リストにはnull型を含めることはできません」エラーがスローされません。

   list.removeAll(Collections.<T>singleton(null));
List<String> colors = new ArrayList<>(
Arrays.asList("RED", null, "BLUE", null, "GREEN"));
// using removeIf() + Objects.isNull()
colors.removeIf(Objects::isNull);
0
cunhaf

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]

並列ストリームは利用可能なプロセッサを利用し、合理的なサイズのリストのプロセスを高速化します。ストリームを使用する前に、ベンチマークを行うことを常にお勧めします。

0
i_am_zero