2013-02-08 14 views
17

HashSet、LinkedHashSet、およびTreeSet実装でnull要素が許可されない理由を知りたいですか? 次のコードをコンパイルしようとすると、nullポインタがスローされます。なぜSetインターフェイスは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+" "); 
    } 
    } 

私をご案内ください。

+14

誤解を招くタイトル()メソッドのTreeMap null値のput()方法は、プットのコード次のように許可されていません呼び出します。例えば。 'HashSet'ドキュメントは明示的に*このクラスがヌル要素を許可すると述べています* – Abdull

答えて

44

私はオートボクシングに頼るのは好きではない理由です。 Javaコレクションはプリミティブを保存できません(そのためにはTroveのようなサードパーティのAPIが必要です)。だから、本当に、あなたはこのようなコードを実行すると:本当に起こっている

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

何です:ハッシュセットにはnullを追加

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

ない問題、その部分の作品ですちょうど良い。あなたはプリミティブなintに自分の価値観を試してみて、UnboxのときあなたのNPEは、後から来る:null値が検出された場合

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

、JVMは、NPEにつながる、int型のプリミティブにそれをVHS版を試みます。あなたはこれを避けるために、あなたのコードを変更する必要があります。

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

実際には '2'は' Integer.valueOf(2) 'を呼び出すことで自動化されます –

+1

ArrayListにnullを追加していて、NPEを投げていません。{ \t \t ArrayListのリスト=新しいArrayListを()。 \t \t \t \t System.out.println( "配列の初期サイズは" + list.size()); \t \t list.add(4)。 \t \t list.add(2)。 \t \t list.add(8); \t \t list.add(9); \t \t list.add(3); \t \t list.add(7); \t \t list.add(1); \t \t list.add(null); \t \t list.add(0,12)。 \t \t \t \tイテレータイテレータ= list.iterator()。 \t \t while(iterator.hasNext()){ \t \t \t System.out.println(iterator.next()); \t \t – nakul

+4

@nakul - 'ArrayList'は' HashSet'と同様にnull要素を許します。あなたのコードの問題は 'HashSet'に追加することとは何の関係もなく、' HashSet'からプリミティブに要素を取り出すことと関係しています。 – Perception

4

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

nullには該当しません。

+3

ほとんどの実装で' null'を受け入れることはできませんが 'null'は' Set'の観点から完全に一意です。ドキュメントには、["一部の実装では、要素に制限があります"(http://docs.oracle.com/javase/7/docs/api/java/util/Set.html))と記載されています。これは定義によるすべての実装で普遍的ではありません(ただし、答えは提供されたコードOPに対して有効です)。 – akaIDIOT

19

1)あなたはコンパイル時にに間違いはありますか?私はそうは思わない、私はコードがnull要素を禁止していない事実java.util.Setインターフェイスの問題として

int i = it.next();

2)で、実行時にNPEをスロー推測、およびいくつかのJCFセット実装ができるようにあまりにも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.

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

-1
私のコードが動作していると、なぜそれが私がNull値が含まれているHashSetのをソートするために試みていると発生する、NullPointer あなたを与えるだろう
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+" "); 
     } 
    } 

} 

それが他のあなた例外与えるだろう、それは動作します良い。

+1

あなたのコードは、 'Integer i = it.next();'あなたが 'int i = it.next();'を使う場合は、例外が発生します。 Iteratorは、next()メソッドからInteger型オブジェクトを取得し、プリミティブ型に格納しようとすると、Integer.javaで定義されたintValue()が呼び出されます。参照はnullなので、nullで呼び出され、結果はNPEになります。 –

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()プリミティブintに整数のオブジェクトを変換するために呼び出されて実行されます。 it.next()がnullを返した場合、null.intValue()が実行され、結果はNullPointerExceptionになります。

整数はintの代わりに使用されているならば、

Integer i = it.next(); 
-1

はHashSetのArrayListのようなコレクションにヌルの追加も例外は存在しませんが、コレクションをソートするために使用されている場合にのみ、問題を作成します。 null以外の場合、イテレータと通常のシナリオでは、リストまたはセットの内容を表示できません。

-1

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

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

+0

"Setインターフェイスは内部的にHashMapを使用します"。いいえ、Setの標準実装の中には、HashMapを使用するものがあります。しかし、インターフェイスはあなたに強制するわけではありません。 – JacksOnF1re

3

Set Interfaceはnullを許可しません.TreeSetでは、要素をソート順に格納するので、新しい要素を追加するたびにvalueを比較してソートします。内部的に何が起こっているかは、新たに追加されたヌル値を既存の値と比較して、NullPointerExceptionをスローします。

String str=null; 
if(str.equals("abc")) 
{ 
} 
//it will throw null pointer exception 

なぜNULL値を許可しないのですか。

4

いいえ、セットインターフェイスはnull値を許可しますその実装のみ、つまりTreeSetはnull値を許可しません。

あなたが繰り返しコードを書いておらず、コードにoTreeSet.add(null)しかありませんが、実行時にNullPointerExceptionがスローされます。

TreeSetクラスのadd()メソッドは内部で

if (key == null) 
    throw new NullPointerException(); 
関連する問題