这些集允许空值。为什么我不能添加空元素?

2022-09-01 11:08:53

我想知道为什么HashSet,LinkedHashSet和TreeSet实现不允许空元素?每当我尝试运行以下代码时,它都会引发空指针异常。

public static void main(String[] args) {

    HashSet<Integer> hashSet = new HashSet<Integer>();

    hashSet.add(2);
    hashSet.add(5);
    hashSet.add(1);
//  hashSet.add(null);  will throw null pointer 
    hashSet.add(999);
    hashSet.add(10);
    hashSet.add(10);
    hashSet.add(11);
    hashSet.add(9);
    hashSet.add(10);
    hashSet.add(000);
    hashSet.add(999);
    hashSet.add(0);

    Iterator<Integer> it = hashSet.iterator();
    while(it.hasNext()){
        int i = it.next();
        System.out.print(i+" ");
    }
    }

请指导我。


答案 1

这就是为什么我不喜欢依赖自动拳击。Java Collections不能存储基元(为此,您将需要像Trove这样的第三方API)。所以,真的,当你执行这样的代码时:

hashSet.add(2);
hashSet.add(5);

真正发生的事情是:

hashSet.add(new Integer(2));
hashSet.add(new Integer(5));

向哈希集添加 null 不是问题,该部分工作正常。当您尝试将值取消装箱到基元 int 中时,您的 NPE 稍后会出现:

while(it.hasNext()){
    int i = it.next();
    System.out.print(i+" ");
}

当遇到该值时,JVM 会尝试将其解装到 int 基元中,从而导致 NPE。您应该更改代码以避免出现这种情况:null

while(it.hasNext()){
    final Integer i = it.next();
    System.out.print(i+" ");
}

答案 2

1)你确定你得到编译时错误吗?我不这么认为,我猜代码在运行时抛出NPE

int i = it.next();

2)事实上,java.util.Set接口并不禁止空元素,一些JCF Set实现也允许空元素:

设置 API -A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element.

HashSet API - .This class permits the null element

LinkedHashSet API -This class provides all of the optional Set operations, and permits null elements

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