2013-02-08 14 views
17

Voglio sapere perché l'implementazione di HashSet, LinkedHashSet e TreeSet non consente elementi null? Ogni volta che provo a compilare il seguente codice, lancia un puntatore nullo.Perché l'interfaccia Set non consente elementi 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+" "); 
    } 
    } 

Per favore guidami.

+14

titolo ingannevole. Per esempio. la documentazione 'HashSet' afferma esplicitamente * Questa classe consente l'elemento nullo. * – Abdull

risposta

44

Questo è il motivo per cui non mi piace fare affidamento su auto-boxing. Le raccolte Java non possono memorizzare primitive (per questo è necessaria un'API di terze parti come Trove). Quindi, in realtà, quando si esegue il codice come questo:

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

Che cosa sta realmente accadendo è:

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

Aggiunta di un nulla al set di hash è non il problema, che le opere di parte va bene. Il vostro NPE viene dopo, quando si tenta di unboxing i valori in un int primitivo:

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

Quando viene rilevato il valore null, la JVM tenta di unboxing in un int primitiva, che porta ad un NPE. Si dovrebbe modificare il codice per evitare questo:

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

In realtà '2' è autoboxed chiamando' Integer.valueOf (2) ' –

+1

Sto aggiungendo null a ArrayList e non sta lanciando NPE.{ \t \t ArrayList list = new ArrayList (); \t \t \t \t System.out.println ("dimensione iniziale della matrice è:" + 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 iteratore iteratore = list.iterator(); \t \t while (iterator.hasNext()) { \t \t \t System.out.println (iterator.next()); \t \t} – nakul

+4

@nakul - 'ArrayList' consente elementi null, proprio come' HashSet'. Il problema con il tuo codice non ha nulla a che fare con l'aggiunta a 'HashSet', ha a che fare con il recupero di elementi da' HashSet' in una primitiva. – Perception

4

Il punto dell'interfaccia Set consiste nell'utilizzare le informazioni sugli elementi (o hashcode o confronti) per rendere l'implementazione più rapida.

null non ha questa informazione.

+3

Mentre è vero che la maggior parte delle implementazioni non accetta' null', 'null' è perfettamente univoco dal punto di vista' Set'. I documenti affermano che ["Alcune implementazioni impostate hanno restrizioni sugli elementi che possono contenere"] (http://docs.oracle.com/javase/7/docs/api/java/util/Set.html); questo non è universale per tutte le implementazioni per definizione (sebbene la risposta sia valida per il codice OP fornito). – akaIDIOT

19

1) Sei sicuro di avere tempo di compilazione errore? Io non la penso così, credo che il codice getta NPE in fase di esecuzione in

int i = it.next();

2) È un dato di fatto l'interfaccia java.util.Set non vieta elementi nulli, e alcune implementazioni JCF Set permetto elementi nulli anche:

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

} 

Il mio codice funziona e perché vi darà nullpointer ho cercato di ordinare hashset che contengono valore Null allora vi darà eccezione altro funziona bene.

+1

Il tuo codice funziona perché hai usato 'Integer i = it.next();' Nel caso in cui tu usi 'int i = it.next();' allora otterrai l'eccezione. Si suppone che Iterator fornisca l'oggetto di tipo Integer dal suo metodo next() e quando proviamo ad archiviarlo in un tipo primitivo viene quindi richiamato intValue() definito in Integer.java. Poiché il riferimento è nullo, viene invocato su un valore null e risulta in NPE. –

1

Set consente di aggiungere null in modo che non sia un problema. In secondo luogo, il programma Java deve essere compilato per primo per convertirlo in codice byte e quindi viene eseguito. NullPointerException è un'eccezione generata durante l'esecuzione. Compilare il tempo non dovrebbe essere un problema. Ora analizziamo il motivo per cui ottieni NPE.

Iterator qui deve fornire l'oggetto del tipo Integer e si desidera memorizzare il risultato nella variabile primitive type int. L'intero è una classe che può avere i riferimenti del suo tipo per fare riferimento a null ma i primitivi non possono contenere valori nulli.

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

Quando int i = it.next(); viene eseguito poi public int intValue() è invocato per convertire l'oggetto di Integer per int primitiva. Quando it.next() restituisce null, viene eseguito il numero null.intValue() il cui risultato è NullPointerException.

Se intero viene usato al posto di int allora non vi sarà alcuna eccezione

Integer i = it.next(); 
-1

Aggiungendo null per le collezioni come HashSet Arraylist creerà problema solo quando la raccolta viene utilizzato per ordinare. Oltre a null funzionerà per l'iteratore e lo scenario normale per visualizzare il contenuto dell'elenco o dell'insieme.

-1

L'interfaccia set utilizza internamente la classe di implementazione HashMap. Quando usiamo add() il nostro valore fornito viene memorizzato in Map come chiave per il valore che crea un oggetto vuoto.

Quindi, la mappa non consente duplicati.

+0

"Imposta interfaccia internamente utilizza HashMap". No. Alcune delle implementazioni standard di Set possono utilizzare una HashMap. Ma l'interfaccia non ti obbliga a farlo. – JacksOnF1re

3

Set Interface non consente null perché in TreeSet, memorizza l'elemento nell'ordine di ordinamento in modo tale che ogni volta che aggiungiamo un nuovo elemento, esso confronta il valore e quindi ordina. così internamente ciò che accade è che confronta il nuovo valore null aggiunto con i valori esistenti, quindi genererà NullPointerException.

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

Ecco perché non consente valori nulli.

4

No, Set Interface non consente il valore nullo solo la sua implementazione, ad esempio TreeSet, non consente il valore nullo.

anche se non hai scritto il codice di iterazione e hai solo oTreeSet.add(null) nel codice che compila e al runtime getta NullPointerException.

TreeSet metodo add() della classe chiama internamente put() metodo TreeMap null valore non è consentito, come di seguito il codice a put metodo()

if (key == null) 
    throw new NullPointerException(); 
Problemi correlati