[introduction to Java] Day24 Java container class (VII) HashMap source code analysis (II)

KeySet

Let's take a look at the keyset first. The member variable keyset in HashMap saves all key sets. In fact, this is the member variable inherited from its parent class abstractmap:

The keyset method is also a method that overrides the parent class:

You can see that the keyset in the abstractmap is an abstractset type, and in the overridden keyset method, the keyset is assigned the keyset type. Turning over the constructor, we can find that the keyset is initialized in the keyset method instead of initializing the keyset in the constructor (similar lazy loading mechanism is used in HashMap). Keyset is an internal class in HashMap. Let's take a look at the overview of this keyset class type:

In fact, keyset inherits from abstractset and covers most of its methods. When traversing keyset, keyiterator will be used. As for splitter, it is designed for parallel traversal and is generally used for parallel operation of stream. The foreach method is used to traverse the operation and apply the functional interface operation action to each element. Let's take a look at a small Chestnut:

The output is as follows:

If you don't remember the status of abstractmap and abstractset in the container framework, you can turn to the first article in this series to see the genealogy of the container family.

But after all that, this keyset. When were the elements put in? Naturally, we will think that when we call the put method to add elements, we put the key into the keyset by the way. Perfect!

Emmmmm, I don't think I found it?

HashIterator

With this question, let's take a look at the mystery in the hashiterator class:

It can be found that in the iterator, when traversing with nextnode, first assign the next reference to current, and then assign next Next is assigned to next, and then the table reference (t = table) in the external class HashMap is obtained. In this way, the key, value and entry can be read directly by traversing the table.

Keyiterator, valueiterator and entryitrator are subclasses of hashiterator. The implementation is also very simple. Only the generic type is modified:

In this way, when the keyset is traversed, it can access the table in the external class HashMap through its iterator. Similarly, values and entryset are traversed in a similar way.

So far, this unsolved mystery has come to an end.

transient

However, careful students may find that member variables such as table, entryset, keyset and value in HashMap are modified with transient. Why do you do this?

First of all, let's talk about the use of transient, which involves serialization in Java. What is serialization?

Of course, just as data storage is for reading, the ultimate purpose of serialization is to restore the original Java object. Otherwise, what will happen after serialization? This process is called deserialization.

When we serialize by implementing the serializable interface, all fields will be serialized. If we don't want a field to be serialized (for example, for security reasons, we don't serialize and transmit sensitive fields), we can use the transient keyword to indicate that we don't want this field to be serialized.

So the problem comes. The table for storing node information is modified with transient. How can data be transmitted during serialization and deserialization???

Emmmm, this involves another painful operation. Serialization is not so simple. After implementing the serializable interface, it will first detect whether there are writeobject and readObject methods in this class. If so, call the corresponding methods:

This is really an extremely bad design... And here is a private method.

Isn't it good to use the default serialization directly? A wave of painstaking operation? Part of the reason is to solve the efficiency problem. Because many buckets in HashMap are empty, serializing them does not make any sense. Therefore, you need to manually use the writeobject () method to serialize only the array of actual storage elements. Another important reason is that the storage of HashMap depends on the hashcode of the object The hashcode () method depends on the specific virtual machine, so the hashcodes of the same object in different virtual machines may be different, and the positions in the HashMap mapped in this way are also different, so the serialized and deserialized objects are different.

Poor translation:

OK, so far, this part is over. Later, we will continue to introduce the most troublesome part of HashMap, treenode

Remember to use your little hand to praise or pay attention. If you think it's good, you're welcome to share it with your friends to make the bug spread further,

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>