3

Enum maps are represented internally as arrays. K[] keyUniverse array of keys and Object[] vals array of values. These arrays are transient. Can you tell me why?

Touchstone
  • 5,575
  • 7
  • 41
  • 48
xCroNic
  • 35
  • 5
  • With HashMap, checking for enum keys is slower than ideal. It is not optimized for enums. – Prashant Apr 03 '15 at 09:49
  • @Prashant that isn't relevant to this question - that is why `EnumMap` exists in the first place. – Andy Turner Apr 03 '15 at 09:54
  • @AndyTurner : i got your point but performance was the main reason to use arrays internally. you can have look at Item 33 in ` Effective java by Joshua bloch` – Prashant Apr 03 '15 at 09:59
  • @Prashant he is asking specifically why the arrays are transient. – Andy Turner Apr 03 '15 at 09:59
  • @AndyTurner : okie i misunderstood!!! – Prashant Apr 03 '15 at 10:00
  • possible duplicate of [Why is the hash table of HashMap marked as transient although the class is serializable](http://stackoverflow.com/questions/9144472/why-is-the-hash-table-of-hashmap-marked-as-transient-although-the-class-is-seria) – Raedwald Apr 03 '15 at 11:32

1 Answers1

1

They are transient to allow making the serialization in a different (better) way. Also entrySet is transient.

private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException
{
    // Write out the key type and any hidden stuff
    s.defaultWriteObject();

    // Write out size (number of Mappings)
    s.writeInt(size);

    // Write out keys and values (alternating)
    for (Map.Entry<K,V> e :  entrySet()) {
        s.writeObject(e.getKey());
        s.writeObject(e.getValue());
    }
}

private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException
{
    // Read in the key type and any hidden stuff
    s.defaultReadObject();

    keyUniverse = getKeyUniverse(keyType);
    vals = new Object[keyUniverse.length];

    // Read in size (number of Mappings)
    int size = s.readInt();

    // Read the keys and values, and put the mappings in the HashMap
    for (int i = 0; i < size; i++) {
        K key = (K) s.readObject();
        V value = (V) s.readObject();
        put(key, value);
    }
}
Bubletan
  • 3,833
  • 6
  • 25
  • 33
  • 2
    Not sure if it's 100% correct though. Noted the "(Cached for performance.)" comment for these fields? Usually it simply does not make sense to serialize duplicate information, so I guess that might have been the reason: they can be calculated from the non-transient fields. – Marvin Apr 03 '15 at 10:13
  • @Marvin, EnumMap does not have other data fields. keyUniverse is just an array of all Enum values of related Enum. It can be read from that Enum at any time but having field is faster. I think that comment "(Cached for performance.)" means this – xCroNic Apr 03 '15 at 10:22
  • @xCroNic: Sure, but you can also recalculate it after deserialization (which is actually done), so there is no need to serialize it (hence the transient modifier). Also, I don't think a field has to be transient to support custom serialization. – Marvin Apr 03 '15 at 10:30
  • @Marvin `s.defaultWriteObject();` and `s.defaultReadObject();` would write and read them if they were not transient. – Bubletan Apr 03 '15 at 10:48
  • So whould it right to say that transient notation works with only default serialization, and present in EnumMap just to point that readObject/writeObject methods are overriden? – xCroNic Apr 03 '15 at 10:53
  • Well practically the transient modifier is only checked by the default implementations of the writing and reading methods, but you can also check them using reflection. They are transient to tell the default methods not to write or read them. – Bubletan Apr 03 '15 at 12:41