NullPointerException in TreeSet when removeAll()

时间:2017-06-15 10:09:50

标签: java nullpointerexception

From the docs of Collection.removeAll():

Throws: NullPointerException - if this collection contains one or more null elements and the specified collection does not support null elements (optional), or if the specified collection is null.

But the code below does still throw a NullPointerException:

public class TestSet { 
    public static void main(String[] args) { 
        Set set1 = new TreeSet(); 
        set1.add("A"); 
        set1.add("B"); 
        Set set2 = new HashSet(); 
        set2.add(null); 
        set1.removeAll(set2); 
    } 
} 

Can someone help me understand this behavior?

2 个答案:

答案 0 :(得分:4)

I guess that Javadoc's conditions for when NullPointerException may be thrown by removeAll are inaccurate.

TreeSet's removeAll relies on AbstractSet's implementation. That implementation iterates over all the elements of the smaller of the two sets.

In your snippet, that's the HashSet, which contains the null element. So removeAll iterates over the HashSet and attempts to remove each element it finds from the TreeSet.

However, remove of TreeSet throws a NullPointerException when trying to remove a null element from as set that uses natural ordering, or its comparator does not permit null elements.

To summarize, the NullPointerException is caused by TreeSet's remove(), which is explained in the Javadoc of remove():

Throws:

ClassCastException - if the specified object cannot be compared with the elements currently in this set

NullPointerException - if the specified element is null and this set uses natural ordering, or its comparator does not permit null elements

It's interesting to note that adding one more element to the HashSet would eliminate the NullPointerException, since in this case both Sets would have the same size, and the implementation of removeAll() would iterate over the elements of the TreeSet.

答案 1 :(得分:2)

好的,从TreeSet的remove方法抛出的Nullpointerexception。以下是Treeset的removeAll()方法

的源代码
public boolean removeAll(Collection<?> c) {
167        boolean modified = false;
168
169        if (size() > c.size()) {
170            for (Iterator<?> i = c.iterator(); i.hasNext(); )
171                modified |= remove(i.next());
172        }

removeAll()方法在内部调用remove()。由于您使用某些null值执行,TreeSet's remove()方法无法处理它,因此无法处理异常。< / p>

  

NullPointerException - 如果指定的元素为null并且此set使用自然排序,或者其比较器不允许null元素