public static void main(String []args){
TreeSet tree = new TreeSet();
String obj = "Ranga";
tree.add(null);
tree.add(obj);
}
据我所知,树木取决于默认的自然分类顺序。因此,JVM内部调用CompareTo((方法。
在上面的示例中,情况是:
obj.compareto(null(;
so,为什么结果为null指针异常?
从1.7开始,null根本不接受null。如果您执行添加,那么我们将获得NullPoInterException。直到1.6 NULL仅作为第一个元素接受。
Java 7-
之前对于非空树,如果我们试图在运行时插入空值,则将获得NullPoInterException。这是因为当树中存在某些元素时,在插入任何对象之前,它将新对象与现有对象进行比较的对象,并决定将新对象放置在何处。因此,通过插入null CompareTo((方法内部抛出NullPoInterException。
treemap添加方法文档
当您尝试在空树上添加null时,它最初不包含任何元素可以比较它,因此没有NPE,当您将第二个元素添加到树中时,TreeT将使用可比较的compareTo((方法来对元素进行排序并放置因此,它将称为Null.comPareto((,该null.compareto((挑衅地通向NPE。
在内部由Treemap备份的TREETET在Java 7 Treemap put(K,V(之前没有null检查K(key(,并且在treemap put(k.v(mehod
中添加了java 7 null检查。Java 7 Treemap放置MeHod代码没有空检查 -
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;
}
}
}
}
从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;
}
我希望这能带领您得出适当的结论。
只是为了维持合同,而自然有序的可比较的incase则执行了行为。
C级的自然排序与e1.compareto(e2(== 0的自然顺序与平等相一致。
在"相对较新的" java版本中(来自第六版(, NullPointerException
有望在第一个add()
调用中抛出:
tree.add(null);
作为TreeSet.add()
Javadoc说:
投掷NullPoInterException - 如果指定的元素为null,并且该集合使用自然排序,则 或其比较器不允许null元素
请注意,它是从JDK 6以这种方式指定的。
例如,JDK 5并未明确说明这一点。
如果您使用旧的Java版本(如Java 5(,请指定。
首先,不要使用原始类型,而是利用仿制药的力量:
TreeSet<String> tree = new TreeSet<>();
至于您的问题:
TreeSet
不再支持添加null
。
来自文档:
public boolean add(E e)
如果指定的元素为null,则抛出
NullPointerException
使用自然订购或其比较器不允许null 元素。
解决此问题的解决方案:
提供一个无效的比较器,其中null
元素将首先出现:
TreeSet<String> tree = new TreeSet<>(Comparator.nullsFirst(Comparator.naturalOrder()));
或提供无效的比较器,其中null
元素将持续:
TreeSet<String> tree = new TreeSet<>(Comparator.nullsLast(Comparator.naturalOrder()));