2013-02-08 2 views
17

Я хочу знать, почему реализация 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+" "); 
    } 
    } 

Прошу вас, руководствоваться мной.

+14

Ложная название. Например. в документации 'HashSet' явно указано * Этот класс разрешает нулевой элемент. * – Abdull

ответ

44

Вот почему я не люблю полагаться на авто-бокс. Коллекции Java не могут хранить примитивы (для этого вам понадобится сторонний API, например Trove). Таким образом, на самом деле, при выполнении такой код:

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

Что происходит на самом деле является:

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

Добавление нуль в хэш-множества не проблема, что часть работ просто хорошо. Ваш NPE приходит позже, когда вы пытаетесь распаковывать свои значения в примитив INT:

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

Когда значение null встречается, то JVM пытается распаковать его в ИНТ примитивно, что приводит к NPE. Вы должны изменить свой код, чтобы избежать этого:

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

Фактически '2' автобоксируется вызовом' Integer.valueOf (2) ' –

+1

Я добавляю null в ArrayList и не бросает NPE.{ \t \t ArrayList list = new 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 Итератор iterator = list.iterator(); \t \t while (iterator.hasNext()) { \t \t \t System.out.println (iterator.next()); \t \t} – nakul

+4

@nakul - 'ArrayList' допускает нулевые элементы, как' HashSet'. Проблема с вашим кодом не имеет ничего общего с добавлением к '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) Вы уверены, что получили время компиляции ошибка? Я не думаю, что это так, я предполагаю, что код генерирует NPE во время выполнения на

int i = it.next();

2) В самом деле интерфейса java.util.Set не запрещают нулевые элементы, а некоторые реализации ГФДА 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

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

} 

Мой код работает и почему это даст вам NullPointer Я попытался разобраться HashSet, которые содержат Null значение, то это даст вам исключение еще работает хорошо.

+1

Ваш код работает, потому что вы использовали 'Integer i = it.next();' Если вы используете 'int i = it.next();' то вы получите исключение. Предполагается, что Iterator предоставляет объект типа Integer из метода next(), и когда мы пытаемся сохранить его в примитивном типе, тогда вызывается intValue(), определенная в Integer.java. Поскольку ссылка имеет значение null, она вызывается с нулевым значением и приводит к NPE. –

1

Set позволяет добавлять нуль, так что это не проблема. Во-вторых, Java-программу необходимо сначала скомпилировать, чтобы преобразовать в байтовый код, а затем выполнить. NullPointerException - исключение, возникшее во время выполнения. Время компиляции не должно быть проблемой. Теперь давайте проанализируем, почему вы получаете NPE.

Iterator здесь предполагается вывести объект типа Integer, и мы хотим сохранить результат в переменной primitive type int. Integer - это класс, который может ссылаться на ссылки своего типа на нуль, но примитивы не могут содержать нулевые значения.

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 примитивного междунар. Когда it.next() возвращает нуль, выполняется null.intValue(), результатом которого является NullPointerException.

если Integer используется вместо междунар тогда не будет исключением

Integer i = it.next(); 
-1

Добавление нуль в коллекции, как HashSet Arraylist будет создавать проблемы только тогда, когда коллекция используется для сортировки. Помимо этого значения null будет работать для итератора и обычного сценария для отображения содержимого списка или набора.

-1

Внутри интерфейса используется класс реализации HashMap. Когда мы используем add(), наше предоставленное значение сохраняется в Map как ключ для значения, он создает пустой объект.

Таким образом, карта не допускает дубликатов.

+0

«Устанавливать интерфейс внутренне использует HashMap». Нет. В некоторых стандартных реализациях Set может использоваться HashMap. Но интерфейс не заставляет вас это делать. – JacksOnF1re

3

Set Interface не разрешает null, поскольку в TreeSet он хранит элемент в порядке сортировки, поэтому каждый раз, когда мы добавляем новый элемент, он сравнивает значение, а затем сортирует. так что внутренне, что происходит, это сравнение нового добавленного значения null с существующими значениями, поэтому он будет генерировать исключение NullPointerException.

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

Вот почему оно не допускает нулевые значения.

4

No, Set Interface разрешает значение null только его реализация, то есть TreeSet не допускает нулевого значения.

, хотя вы не указали итерационный код и имеете только код oTreeSet.add(null) в своем компилируемом коде и в runtime it throws NullPointerException.

TreeSetadd() метод класса внутренне вызывает put() метод значения TreeMap null не допускается, как показано ниже код в метод пут()

if (key == null) 
    throw new NullPointerException(); 
Смежные вопросы