首先,我在TreeSet中插入null.之后我插入任何其他值为什么它给NPE?

Shr*_*ale 1 java collections treeset

 public static void main(String []args){
    TreeSet tree = new TreeSet();
    String obj = "Ranga";
    tree.add(null);
    tree.add(obj);
 }
Run Code Online (Sandbox Code Playgroud)

据我所知,TreeSet依赖于默认的自然排序顺序.因此JVM在内部调用compareTo()方法.

在上面的例子中,案例是:

 public static void main(String []args){
    TreeSet tree = new TreeSet();
    String obj = "Ranga";
    tree.add(null);
    tree.add(obj);
 }
Run Code Online (Sandbox Code Playgroud)

那么,为什么结果是空指针异常.

Afg*_*gan 5

从1.7开始,TreeSet完全不接受null.如果你强制添加,那么我们将得到NullPointerException.直到1.6 null才被接受为第一个元素.

在java 7之前 -

对于非空TreeSet,如果我们尝试在运行时插入空值,您将得到NullPointerException.这是因为当树中存在某些元素时,在插入任何对象之前,它会使用compareTo()方法将新对象与现有对象进行比较,并决定放置新对象的位置.因此,通过插入null,compareTo()方法在内部抛出NullPointerException.

TreeMap添加方法文档

当你尝试在空TreeSet上添加null时,它最初不包含任何要比较的元素,因此它的添加没有NPE,当你将在TreeSet中添加第二个元素时,TreeSet将使用Comparable compareTo()方法对元素进行排序并放入TreeSet对象中因此它会调用null.compareTo(),它会导致NPE.

TreeSet内部支持TreeSet,在Java 7 TreeMap put(K,V)没有对K(key)进行空检查之前,从Java 7中添加了null检查在TreeMap put(KV)中添加了mehod

之前java 7 TreeMap把mehod代码没有null检查 -

  public V put(K key, V value) {
        Entry<K,V> t = root;

        if (t == null) {
            incrementSize();
            root = new Entry<K,V>(key, value, null);
            return null;
       }

        while (true) {
            int cmp = compare(key, t.key);
            if (cmp == 0) {
                return t.setValue(value);
            } else if (cmp < 0) {
                if (t.left != null) {
                    t = t.left;
                } else {
                    incrementSize();
                    t.left = new Entry<K,V>(key, value, t);
                    fixAfterInsertion(t.left);
                    return null;
                }
            } else { // cmp > 0
                if (t.right != null) {
                    t = t.right;
                } else {
                    incrementSize();
                    t.right = new Entry<K,V>(key, value, t);
                    fixAfterInsertion(t.right);
                    return null;
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

从java 7中你可以看到null检查密钥,如果它为null它将抛出NPE.

public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        compare(key, key); // type (and possibly null) check

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    int cmp;
    Entry<K,V> parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    else {
        if (key == null)
            throw new NullPointerException();
        Comparable<? super K> k = (Comparable<? super K>) key;
        do {
            parent = t;
            cmp = k.compareTo(t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    Entry<K,V> e = new Entry<>(key, value, parent);
    if (cmp < 0)
        parent.left = e;
    else
        parent.right = e;
    fixAfterInsertion(e);
    size++;
    modCount++;
    return null;
}
Run Code Online (Sandbox Code Playgroud)

我希望这会引导你得到正确的结论.