29

HashSet、LinkedHashSet、および TreeSet の実装で null 要素が許可されない理由を知りたいですか? 次のコードを実行しようとすると、null ポインター例外がスローされます。

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+" ");
    }
    }

私を案内してください。

4

11 に答える 11

64

これが、オートボクシングに頼りたくない理由です。Java コレクションはプリミティブを格納できません (そのためには、 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+" ");
}

null値が検出されると、JVM はそれを int プリミティブにアンボックスしようとしますが、これにより NPE が発生します。これを回避するには、コードを変更する必要があります。

while(it.hasNext()){
    final Integer i = it.next();
    System.out.print(i+" ");
}
于 2013-02-08T15:43:39.147 に答える
21

1)コンパイル時エラーが発生することを確信していますか? 私はそうは思わない.コードは実行時にNPEをスローすると思う.

int i = it.next();

2) 実際のところ、java.util.Set インターフェースは null 要素を禁止しておらず、一部の JCF Set 実装では null 要素も許可されています。

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.

ハッシュセット 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

于 2013-02-08T14:50:29.160 に答える
8

いいえ、Set Interface は null 値のみを許可します。つまりTreeSet、null 値は許可しません。

反復コードを記述しておらずoTreeSet.add(null)、コード内でのみコンパイルし、実行時に NullPointerException をスローする場合でも。

TreeSetクラスのadd()メソッドは、内部put()で TreeMap クラスのメソッドを呼び出します。 nullput() メソッドの以下のコードのように、値は許可されていません

if (key == null)
     throw new NullPointerException();
于 2016-10-20T14:34:32.020 に答える
5

インターフェイスのポイントはSet、要素に関する情報 (ハッシュコードまたは比較) を使用して、実装を高速化することです。

nullはその情報を持っていません。

于 2013-02-08T14:29:42.120 に答える
1

Set では null を追加できるため、問題はありません。次に、Java プログラムをコンパイルしてバイトコードに変換してから実行する必要があります。NullPointerException実行時にスローされる例外です。コンパイル時間は問題になりません。次に、NPE になる理由を分析してみましょう。

Iteratorここでは、タイプのオブジェクトを出力することになっており、結果を変数Integerに格納したいと考えています。primitive type int整数は、null を参照するためのその型の参照を持つことができるクラスですが、プリミティブは null 値を保持できません。

Iterator<Integer> it = hashSet.iterator(); // Iterator of Type Integer
while(it.hasNext()){
    int i = it.next(); // it.next outputs Integer, but result is tried to be held in a primitive type variable
    System.out.print(i+" ");
}

int i = it.next();実行されると、public int intValue()が呼び出されて、Integer のオブジェクトがプリミティブ int に変換されます。it.next()null を返すとnull.intValue()が実行され、結果は になりNullPointerExceptionます。

int の代わりに Integer を使用すると、例外は発生しません。

Integer i = it.next();
于 2016-04-10T16:58:33.870 に答える
0
public class JavaHashSetTest {


    public static void main(String[] args) {
        Set<Integer> hashset= new HashSet<Integer>();

        hashset.add(null);
        hashset.add(22);
        hashset.add(222);
        hashset.add(null);
        hashset.add(11);
        hashset.add(233);
        //  TreeSet<String> tset=hashset;

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

}

私のコードは機能しており、Nullpointer が表示される理由 Null 値を含むハッシュセットをソートしようとしましたが、例外が発生し、それ以外の場合は正常に動作します。

于 2015-05-28T09:37:44.593 に答える
-1

Set インターフェイスは内部的に HashMap 実装クラスを使用します。add() を使用するたびに、提供された値が値のキーとして Map に格納され、空のオブジェクトが作成されます。

したがって、マップは重複を許可しません。

于 2016-07-03T03:23:54.133 に答える
-1

HashSet Arraylist のようなコレクションに null を追加すると、コレクションがソートに使用される場合にのみ問題が発生します。それ以外の null は、イテレータと通常のシナリオで機能し、リストまたはセットの内容を表示します。

于 2016-04-22T15:03:04.023 に答える