我可以使用非空的hashmap而没有键吗?

时间:2013-02-27 09:55:32

标签: java java-ee map hashmap key

我在Java HashMap上有一个奇怪且意外的行为,代码的一部分仅用于测试。

要在将对象存储到会话之前尝试为对象设置唯一ID,我会使用if{}else{}语句,但我发现自己的应用中出现了错误。

生成ID用于测试目的,因为当前没有数据库实际存储数据,同时存储在会话中。

这是我的代码片段:

 ...
 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()的{​​{1}}为空

  4. 但测试未输入Map<Integer,Booking> bookings声明

  5. 另一方面,在一个全新的会话中(在重新启动浏览器或退出并重新登录之后),测试确实按预期输入了if语句。

    经过测试,我改变了if的条件 至(bookings==null) 进一步的测试表明,在新会议上注册预订时仅使用(bookings==null || bookings.isEmpty())会导致NPE。

    所以我想知道Map是否有可能是非null而没有值(显然,是的,但我也问自己是怎么回事)以及它之后怎么没有返回null被完全清空?

    虽然我在(bookings.isEmpty()语句之后得到它是空的,但在new调用之后它是怎么回事?这似乎很明显,因为会话中还没有存储Map,但同时由于没有session.getAttribute()语句,它似乎很奇怪。

3 个答案:

答案 0 :(得分: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;
}

回答这个问题:

  

它完全清空后怎么没有返回null?

看看这段代码:

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

我从未在地图中输入任何键/值对,因此它是空的。这就是我将一些键/值对放入其中的状态,然后再将其删除。 map为空,但没有理由nullnull。如果是{{1}}我们将来再也无法添加任何内容。

答案 1 :(得分:1)

HashMap可以是null(如果没有初始化)或为空(如果已初始化但未输入任何对象)。 从地图中删除对象会将其返回“空”状态(并且 null)。

new语句为对象分配内存,并将其创建为空HashMap(和 null)

答案 2 :(得分:1)

null 并且为空是完全不同的概念。当变量(引用类型)为null时,它指向无处。你根本没有HashMap。你只有一个空的指针(不是空的HashMap)。您可以使用HashMap创建新的bookings = new HashMap<Integer, Booking>()。之后,你有 HashMap。你实际上有一个HashMap,但里面什么都没有。

同样,当您从HashMap中删除所有元素时,它将变为为空,而不是 null 。要使它null,你必须明确地这样做:

bookings = null;