30
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Listに格納されたNullの要素を一括削除したい

Last updated at Posted at 2014-11-30

経緯

Listに入っているオブジェクトの中から、Nullは削除したい…。
Listにそんなメソッドきっと持ってるでしょ、うん。
いってみよう、やってみよう。

実装してみた

ArraySample.java

package main.java;

import java.util.ArrayList;
import java.util.List;

public class ArraySample {

    public static void main(String[] args) {
        List<String> testString = new ArrayList<String>();
        testString.add("hoge");
        testString.add(null);
        testString.add("fuga");
        testString.add(null);

        testString.removeAll(null); // これで一括削除だ!!
        for(String str : testString) {
            System.out.println(str);
        }
    }
}

実行してみた

Exception

Exception in thread "main" java.lang.NullPointerException
	at java.util.ArrayList.batchRemove(ArrayList.java:700)
	at java.util.ArrayList.removeAll(ArrayList.java:671)
	at main.java.ArraySample.main(ArraySample.java:15)

ちゅーーーん。。。
ぬるぽで落ちやがる…。

ArrayListの中を見てみる

(仕方ないから)何故だろうと、ArrayListの中身を見てみる。

ArrayList.java

    public boolean removeAll(Collection<?> c) {
        return batchRemove(c, false);
    }

    private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement) ここ
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

ほへぇ。
"ここ!"の部分で、引数で渡したnullに対して、
null.contains(elementData[r]) == complement)
してる…。
nullにcontainsメソッドなんてないから、NullPointerExceptionで落ちる。

再実装してみた

と、いうことで、
testString.removeAll(null); // これで一括削除だ!!
を、
testString.removeAll(Collections.singleton(null)); // 今度はこれで一括削除だ!
に修正して実行してみる。
いってみよう、やってみよう。

ArraySample.java

package main.java;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ArraySample {

    public static void main(String[] args) {
        List<String> testString = new ArrayList<String>();
        testString.add("hoge");
        testString.add(null);
        testString.add("fuga");
        testString.add(null);

        testString.removeAll(Collections.singleton(null)); // 今度はこれで一括削除だ!

        for(String str : testString) {
            System.out.println(str);
        }
    }
}

再実行だぞ★

result

hoge
fuga

うまくいったー^^★

Collections.singleton(null)って何なのよ

CollectionsインターフェースのJavaDocを読んでみる。

static <T> Set<T>
singleton(T o)
指定されたオブジェクトだけを格納している不変のセットを返します。

ふむ…。
nullを指定したら、ちゃんとnullを格納しているSetを返してくれるわけだ…。
= removeAllで引数に渡しても、"null"ではなく、"nullが格納されたSet"な為、NullPointerExceptionにはならない…。

ふむふむ。勉強になった。

30
27
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?