経緯
Listに入っているオブジェクトの中から、Nullは削除したい…。
Listにそんなメソッドきっと持ってるでしょ、うん。
いってみよう、やってみよう。
実装してみた
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 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の中身を見てみる。
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)); // 今度はこれで一括削除だ!
に修正して実行してみる。
いってみよう、やってみよう。
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);
}
}
}
再実行だぞ★
hoge
fuga
うまくいったー^^★
Collections.singleton(null)って何なのよ
CollectionsインターフェースのJavaDocを読んでみる。
static <T> Set<T>
singleton(T o)
指定されたオブジェクトだけを格納している不変のセットを返します。
ふむ…。
nullを指定したら、ちゃんとnullを格納しているSetを返してくれるわけだ…。
= removeAllで引数に渡しても、"null"ではなく、"nullが格納されたSet"な為、NullPointerExceptionにはならない…。
ふむふむ。勉強になった。