2017-06-15 44 views
3

Collection.removeAll()文檔:NullPointerException異常在TreeSet中時的removeAll()

拋出:NullPointerException - 如果此集合包含一個或多個 null元素,並且指定collection不支持 null元素(可選),或者指定的集合是否爲空。

但下面的代碼確實還拋出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); 
    } 
} 

有人可以幫助我理解這種行爲?

+1

不,它不是重複,你只是指向質疑給出了認定中NPE在這裏,我正在問一些不同的東西 –

+0

@ domdom - 請刪除重複的標籤,並仔細閱讀問題。 –

+1

「這個集合」是指'removeAll'調用的接收者,即'set1'。該集合中沒有空元素。 –

回答

4

我想Javadoc的NullPointerException可能由removeAll拋出的條件是不準確的。

TreeSetremoveAll依賴於AbstractSet的實現。該實現迭代了兩組中較小組的所有元素。

在你的代碼片段中,這是HashSet,其中包含null元素。因此removeAll重複通過HashSet並嘗試從TreeSet中刪除找到的每個元素。

然而,TreeSetremove試圖從作爲設置uses natural ordering, or its comparator does not permit null elements移除null元件時引發一個NullPointerException

拋出:: - 如果指定的對象不能相比

ClassCastException異常

總之,NullPointerExceptionTreeSetremove(),其在的remove()的Javadoc解釋引起當前在這個集合中的元素

NullPointerException - 如果指定的元素是nu LL並且此set使用自然順序,或者它的比較器不允許使用null元素

有趣的是要注意添加一個多元素的HashSet將消除NullPointerException,因爲在這種情況下,兩個Set s就具備相同的大小,並且removeAll()的實現將迭代TreeSet的元素。

+0

根據堆棧跟蹤,NPE源自'getEntry()',不是嗎?但是我猜這是挑剔的。 – domsson

+0

@dom我可以指出NPE的確切來源,但由於'TreeSet'的'remove()'已經在Javadoc中聲明它會在嘗試刪除'null'元素時拋出一個NPE,它沒有似乎沒有必要。 – Eran

+0

現在,誰會向Oracle彙報(以及如何)? :) – domsson

2

好吧,Nullpointerexception從TreeSet的remove方法拋出。下面是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()方法無法處理它,所以異常。

NullPointerException - 如果指定的元素爲null,並且此set使用自然順序,或者其比較器不允許使用null元素

+0

*並且指定的集合不允許爲指定集合的​​空元素*?一個正在被刪除或參數? –

+0

@ScaryWombat你調用removedAll()的那個。 –

+0

@ScaryWombat:「指定的集合」是參數(而「此集合」是其方法被調用的對象)。 – ruakh