2011-08-18 15 views
27

HashMap implementa l'interfaccia Serializable; quindi può essere serializzato. Ho esaminato l'implementazione di HashMap e la tabella Entry [] è contrassegnata come transitoria. Poiché la tabella Entry [] è quella che memorizza l'intero contenuto della mappa e se non può essere serializzata, in che modo viene ricostruita la mappa durante la de-serializzazioneSerializzabilità HashMap

risposta

32

Se guardi a the source vedrai che non lo fa invocare il meccanismo predefinito di serializzazione, ma scrive manualmente tutte le voci (come un flusso alternato di chiavi e valori):

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

Questo è più compatta rispetto alla matrice, che può contenere il numero di voci vuote e catene e overhead per Map $ Entry wrappers.

Si noti che invoca ancora defaultWriteObject per i campi "facili". Affinché funzioni, deve contrassegnare tutto il resto come transient.

+0

Trovo interessante il fatto che il fattore di carico di HashMap non sia serializzato. Quindi questa informazione si sta perdendo. –

+1

@PeterWippermann: sei sicuro? Questo 'loadFactor' non è transitorio, dovrebbe essere contenuto nell'output prodotto da' defaultWriteObject'. (In effetti, il commento nella fonte subito prima della chiamata a defaultWriteObject menziona direttamente questo). – Thilo

+1

Oh, hai ragione, certo! Non ho notato, che sarebbe stato interessato dalla serializzazione predefinita. Grazie per avermi segnalato questo! :-) –

8

HashMap si occupa della propria serializzazione mediante l'utilizzo dei metodi writeObject e readObject.

4

HashMaps non serializza gli oggetti Entry durante la serializzazione. Dai un'occhiata al suo metodo writeObject.

I javadocs spiegano:

La capacità del HashMap (la lunghezza della matrice benna) è emessa (int), seguita dalla misura (un int, il numero di valori-chiave mappature), seguito dal tasto (oggetto) e dal valore (oggetto) per ogni mappatura dei valori-chiave . I mapping dei valori-chiave sono emessi in nessun particolare ordine .

Se si osserva il metodo readObject, si vedrà come la tabella di inserimento viene ricostruita utilizzando le dimensioni, le chiavi e i valori.