简体   繁体   English

为什么“java.util.HashMap”中的成员字段“table”是瞬态的?

[英]Why member field 'table' in 'java.util.HashMap' is transient?

I learnt, the transient keyword prevents the values of instance fields that are declared with transient keyword from being persisted when an object is serialized.我了解到,当对象被序列化时, transient关键字会阻止使用transient关键字声明的实例字段的被持久化。

Below is the code from java.util.HashMap :下面是来自java.util.HashMap的代码:

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {

             ....
             static class Node<K,V> implements Map.Entry<K,V> {...}
             transient Node<K,V>[] table;
}

Why values of instance field table are not part of serialization?为什么实例字段table值不是序列化的一部分? Because values of table field is the actual content of class HashMap instance from implementation perspective.因为从实现的角度来看, table字段的值是class HashMap实例的实际内容。

Note: here is one exercise on using transient keyword.注意: 是一个关于使用瞬态关键字的练习。

How does one decide to not serialize a member by giving transient modifier?如何通过提供瞬态修饰符来决定不序列化成员?

  1. When the field refers to a resource that doesn't make sense to be serialised.当该字段引用没有意义被序列化的资源时。 For example, a OutputStream or a Window handle.例如,OutputStream 或 Window 句柄。
  2. When the field can be reconstructed from the other information that is serialised.何时可以从序列化的其他信息重建字段。 This helps in reducing the amount of data that need to be written.这有助于减少需要写入的数据量。

For example, why member field table is not part of serialization?例如,为什么成员字段表不是序列化的一部分?

Because (2).因为(2)。 Have a look at the readObject method in the HashMap class.查看HashMap类中的readObject方法。 The table field is reconstructed using the other information in the class.使用类中的其他信息重建table字段。

An instance of HashMap has two parameters that affect its performance: initial capacity and load factor. HashMap 的实例有两个影响其性能的参数:初始容量和负载因子。 The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created.容量是哈希表中的桶数,初始容量就是哈希表创建时的容量。

Since the 'table', in the example you mentioned, gets constructed with other 2 params and used by this data structure for representation, one need not bother about its serialization.由于在您提到的示例中,“表”是用其他 2 个参数构造的,并由该数据结构用于表示,因此无需担心其序列化。

Eg you could see it below :例如,您可以在下面看到它:

   public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);

        // Find a power of 2 >= initialCapacity
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1;

        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);
        table = new Entry[capacity];
        init();
    }

Because Node<K, V>[] table is sparse, it is a waste of time to serialize all this array.因为Node<K, V>[] table是稀疏的,所以序列化所有这个数组是浪费时间。 Instead, we only need to serialize the non-empty elements in the array which is enough to reconstruct the table later.相反,我们只需要序列化数组中的非空元素,这足以在以后重建表。

    void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
        Node<K,V>[] tab;
        if (size > 0 && (tab = table) != null) {
            for (int i = 0; i < tab.length; ++i) {
                for (Node<K,V> e = tab[i]; e != null; e = e.next) {
                    s.writeObject(e.key);
                    s.writeObject(e.value);
                }
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM