HashMap Serializability

43,675

Solution 1

If you look at the source you will see that it does not rely on the default serialization mechanism, but manually writes out all the entries (as an alternating stream of keys and values):

/**
  * 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());
                }
            }
        }

This is more compact than the array, which can contain many empty entries and link chains and overhead for Map$Entry wrappers.

Note that it still invokes defaultWriteObject for the "easy" fields. In order for that to work, it has to mark everything else as transient.

Solution 2

HashMap takes care of its own serialization through the use of the writeObject and readObject methods.

Solution 3

HashMaps don't serialize their Entry objects during serialization. Take a look at its writeObject method.

The javadocs explain:

The capacity of the HashMap (the length of the bucket array) is emitted (int), followed by the size (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.

If you look at the readObject method you will see how the Entry table is rebuilt using the size, keys and values.

Share:
43,675
java_geek
Author by

java_geek

Updated on August 18, 2020

Comments

  • java_geek
    java_geek almost 4 years

    HashMap implements the Serializable interface; so it can be serialized. I have looked at the implementation of HashMap and the Entry[] table is marked as transient. Since the Entry[] table is the one that stores the entire contents of the Map and if it cannot be serialized, how is the Map constructed back during de-serialization

  • Peter Wippermann
    Peter Wippermann almost 10 years
    I find it interesting that the load factor of HashMap is not serialized. So this information is getting lost.
  • hansvb
    hansvb almost 10 years
    @PeterWippermann: Are you sure? This loadFactor is not transient, it should be contained in the output produced by defaultWriteObject. (In fact, the comment in the source right before the call to defaultWriteObject directly mentions this).
  • Peter Wippermann
    Peter Wippermann almost 10 years
    Oh you're right of course! I didn't notice, that it would be affected by the default serialisation. Thanks for pointing me to this! :-)