2013-02-27 3 views
0

У меня было странное и неожиданное поведение на java HashMap, часть кода, предназначенная исключительно для тестирования.Могу ли я иметь непустую хэш-карту без ключей?

Чтобы попытаться установить уникальный идентификатор объекта перед его сохранением в сеансе, я использую оператор if{}else{}, но я обнаружил ошибку в своем приложении.

Идентификатор создается для тестовых целей, так как в настоящее время нет базы данных для фактического хранения данных, которые хранятся в сеансе тем временем.

Вот мой фрагмент кода:

... 
HttpSession session = request.getSession(); 
Map<Integer, Booking> bookings = (HashMap<Integer, Booking>) session.getAttribute(SESSION_BOOKINGS); 

// Generates ID 
if (bookings == null) 
{ 
     bookings= new HashMap<Integer, Booking>(); 
     identificator = 1; 
} 
else 
{ 
     Object[] arrayKeys = (Object[]) bookings.keySet().toArray(); 
     Arrays.sort(arrayKeys); 
     identificator = (Integer) arrayKeys[arrayKeys.length - 1] + 1; 
} 

... 
//... The rest is setting the ID to the current worked on booking, 
//... putting the ID/booking pair in the bookings map 
//... and storing the map in session, which worked fine 

ошибка пришла после удаления номер на карте, когда карта содержала только один. Когда я пытался зарегистрировать еще один после этого, я получил сообщение об ошибке со следующей причиной ошибки java.lang.ArrayIndexOutOfBoundsException: -1 и следом, связанным с последней строкой моего else заявления: identificator = (Integer) arrayKeys[arrayKeys.length - 1] + 1;

Итак:

  1. arrayKeys.length -1 == -1 // true
  2. это означает, что arrayKeys.length == 0 // true
  3. , который в свою очередь означает, что keySet() от Map<Integer,Booking> bookings пуст

  4. пока тест не входит в if заявление

С другой стороны, на новой сессии (либо после перезапуска браузера или выхода из системы и снова), тест сделал ввести если заявление как ожидается.

После тестирования I сменил телефон с (bookings==null)
на (bookings==null || bookings.isEmpty()).
Дальнейшие испытания показали, что использование только (bookings.isEmpty() приводит к NPE при регистрации бронирования на новом сеансе.

Так что мне было интересно, если бы карта была не нулевой, без значения в ней (очевидно, да, но я также спрашиваю себя, как), и почему она не вернулась к null после он был полностью опустошен?

И хотя я понимаю, что после заявления new, как это происходит после звонка session.getAttribute()? Это кажется очевидным, так как карты еще не сохранены в сеансе, но в то же время кажется странным, поскольку не было new.

ответ

1

Если

if (bookings == null) 

правда, чем у вас нет карты (это отличается от пустой карты).

Если выполняется блок else, это означает, что на карту ссылаются. Вы ничего не знаете о количестве элементов на карте.Вы, наверное, хотите что-то вроде этого:

if (bookings == null) 
{ 
    bookings= new HashMap<Integer, Booking>(); 
    identificator = 1; 
} else if (bookings.isEmpty()) 
{ 
    identificator = 1; 
} 
else 
{ 
    identificator = Collections.max(bookings.keySet()) + 1; 
} 

Чтобы ответить на этот вопрос:

как же он не вернулся в нуль после его полного опорожнения?

Посмотрите на этот код:

Map<Integer, Booking> map = new HashMap<>(); 

Я никогда не введены какие-либо пары ключ/значение в карте, так что она пуста. Это то же самое состояние, как если бы я вложил в него некоторые пары ключ/значение, а затем снова удалил их. map пуст, но для этого нет никаких причин null. Если бы это было null, мы больше ничего не могли добавить в будущем.

1

A HashMap может быть null (если не инициализирован) или пустым (если инициализирован, но объект не был введен). Удаление объекта с карты возвращает его в состояние «пусто» (и неnull).

new оператор выделяет память для объекта, и создать его как пустой HashMapне нуля)

1

Будучи нулевой и быть пустой совершенно разные понятия. Когда переменная (ссылочный тип) имеет значение null, она указывает на никуда. У вас нет HashMap. У вас просто пустой указатель (не пустой HashMap). Вы создаете новый HashMap, используя bookings = new HashMap<Integer, Booking>(). После этого у вас есть пустоHashMap. У вас есть HashMap, но в нем нет ничего.

Кроме того, когда вы удалите все элементы из HashMap, становится пустого, а не нулевой. Чтобы сделать это null, вы должны явно сделать это:

bookings = null; 
Смежные вопросы