【问题标题】:HashMap SerializabilityHashMap 可序列化
【发布时间】:2011-10-29 12:53:44
【问题描述】:

HashMap 实现了 Serializable 接口;所以可以序列化。我查看了 HashMap 的实现,Entry[] 表被标记为瞬态。由于Entry[]表是存储Map全部内容的表,如果不能序列化,那么反序列化时Map是如何构造回来的

【问题讨论】:

    标签: java serialization hashmap


    【解决方案1】:

    如果您查看the source,您会发现它不依赖默认的序列化机制,而是手动写出所有条目(作为键和值的交替流):

    /**
      * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
      * serialize it)
      *
      * @serialData The <i>capacity</i> of the HashMap (the length of the
      *             bucket array) is emitted (int), followed by the
      *             <i>size</i> (an int, the number of key-value
      *             mappings), followed by the key (Object) and value (Object)
      *             for each key-value mapping.  The key-value mappings are
      *             emitted in no particular order.
      */
          private void writeObject(java.io.ObjectOutputStream s)
                 throws IOException
             {
                 Iterator<Map.Entry<K,V>> i =
                     (size > 0) ? entrySet0().iterator() : null;
    
                // Write out the threshold, loadfactor, and any hidden stuff
                s.defaultWriteObject();
    
                // Write out number of buckets
                s.writeInt(table.length);
    
                // Write out size (number of Mappings)
                s.writeInt(size);
    
                // Write out keys and values (alternating)
                if (i != null) {
                    while (i.hasNext()) {
                        Map.Entry<K,V> e = i.next();
                        s.writeObject(e.getKey());
                        s.writeObject(e.getValue());
                    }
                }
            }
    

    这比数组更紧凑,数组可以包含许多空条目和链接链以及 Map$Entry 包装器的开销。

    请注意,它仍然为“简单”字段调用defaultWriteObject。为了使它起作用,它必须将其他所有内容标记为transient

    【讨论】:

    • 我觉得有趣的是 HashMap 的负载因子没有序列化。所以这些信息正在丢失。
    • @PeterWippermann:你确定吗?这个loadFactor 不是瞬态的,它应该包含在defaultWriteObject 产生的输出中。 (事实上​​,在调用 defaultWriteObject 之前的源代码中的注释直接提到了这一点)。
    • 哦,你当然是对的!我没有注意到它会受到默认序列化的影响。感谢您指出这一点! :-)
    【解决方案2】:

    HashMap 通过使用writeObjectreadObject 方法来处理自己的序列化。

    【讨论】:

      【解决方案3】:

      HashMap 在序列化过程中不会序列化它们的 Entry 对象。看看它的writeObject 方法。

      javadocs 解释:

      HashMap的容量(桶数组的长度)为 发出(int),后跟大小(一个int,key-value的个数 映射),然后是每个的键(对象)和值(对象) 键值映射。键值映射不会特别发出 顺序。

      如果您查看readObject 方法,您将看到如何使用大小、键和值重建条目表。

      【讨论】:

        猜你喜欢
        • 2015-12-23
        • 2014-02-10
        • 2011-08-26
        • 1970-01-01
        • 1970-01-01
        • 2014-10-19
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        相关资源
        最近更新 更多