Java AbstractMap abstract class, Java AbstractMap

Source: Internet
Author: User

Java AbstractMap abstract class, Java AbstractMap

Jdk1.8.0 _ 144

The AbstractMap abstract class implements some simple and common methods, and is not difficult. However, there are two methods in this abstract class that deserve attention. The implementation of the source code of the keySet and values methods can be said to be a textbook model.

Abstract classes are usually implemented as a skeleton, and public methods are implemented for each subclass. The previous article explains the Map interface. This article analyzes and studies the AbstractMap abstract class.

In Java, there are quite a few Map-type data structures. AbstractMap implements some Map interface methods as their skeleton, that is, it provides a public method for its subclass of various maps, map methods that are not implemented may be different.

An abstract class cannot directly create an instance of an abstract class using the new keyword, but it can have a constructor. AbstractMap provides a parameter-free constructor method modified by protected, which means that only its subclass can be accessed (of course, it is an abstract class and other classes cannot be instantiated directly ), that is to say, only its subclass can call the construction method without parameters.

An Entry interface is defined in the Map interface. This interface is an internal implementation of Map ing to maintain a key-value pair, and key-value is stored in this Map. Entry. AbstractMap implements this internal interface. There are two implementations: one is a variable SimpleEntry and the other is an immutableentry.

Public static class SimpleEntry <K, V> implements Entry <K, V>, java. io. Serializable

Implemented the Map. Entry <K, V> interface and Serializable ).

Its method is simple to operate on the stored values of values. The definition of the key value is a final modification, which means an immutable reference. In addition, the setValue method is a little special. The stored value does not return the saved value, but the old value returned. What needs to be learned is the equals and hashCode methods it overwrites.

1 public boolean equals (Object o) {2 if (! (O instanceof Map. Entry) // determines whether the parameter is of the Map. Entry type. If equals is equal, it must be of the same type 3 return false; 4 Map. Entry <?,?> E = (Map. Entry <?,?>) O; // convert the Object type to Map. Entry type. The parameter here uses "?" Instead of "K, V", it is because the generic type is erased at runtime, And the compiler does not know the specific K. What type is V 5 return eq (key, e. getKey () & eq (value, e. getValue (); // the key and value respectively call the eq method for determination. equals is equal when both returns true. 6}
1 private static boolean eq (Object o1, Object o2) {2 return o1 = null? O2 = null: o1.equals (o2); // This three-Object operator is also very simple, but note that although o1 and o2 are of the Object type, the equals method of Object type is referenced through "=", so do not think that there is a problem here, because in reality, the o1 type may be String, although it is converted to Object, therefore, the String # equals method is called when the equals method is called. 3}

To correctly override and use the equals method, you usually need to override the hashCode method.

1 public int hashCode () {2 return (key = null? 0: key. hashCode () ^ (value = null? 0: value. hashCode (); // when the values of key and value are not null, their hashCode is used for an exclusive or operation. 3}

Public static class SimpleImmutableEntry <K, V> implements Entry <K, V>, java. io. Serializable SimpleImmutableEntry

An Entry defined as immutable is actually immutable because it does not provide the setValue method. It cannot be modified by using the setValue method when multiple threads access it at the same time. Compared with SimpleEntry, its key and value member variables are defined as the final type. An UnsupportedOperationException will be thrown when the setValue method is called.

Its equals and hashCode methods are consistent with SimpleEntry.

Next, let's check which Map interfaces are implemented in the AbstractMap abstract class.

Public int size ()

The Map defines an entrySet method. The returned value is the Set of Map. The size method of the Set is called directly, that is, the size of the Map.

Public boolean isEmpty ()

Call the above size method. If it is equal to 0, it is null.

Public boolean containsKey (Object key)

The implementation of this method is relatively simple. by calling the entrySet method, the iterator of the Set traverses Map. Entry and compares it with the parameter key. Map can store key values that are null. Because key = null is stored in Map, it is special (hashCode value cannot be calculated). Therefore, we also judge whether the parameter key is null.

Public boolean containsValue (Object value)

This method is consistent with containsKey.

Public V get (Object key)

The implementation of this method is similar to the preceding two methods. The difference is that the return value is boolean, And the return value is boolean.

Public V put (K key, V value)

The method used to store key-value pairs in Map is not implemented. An UnsupportedOperationException is thrown directly.

Public V remove (Object key)

You can use the key parameter to delete the specified key-value pair in the Map. This method is also very simple. It also uses the Iterator to traverse the Set of Map. Entry, find the corresponding key value, and call the Iterator # remove Method to delete Map. Entry.

Public void putAll (Map <? Extends K ,? Extends V> m)

This method also easily traverses the input Map and calls the put Method to store it.

Public void clear ()

Call the entrySet method to obtain the Set and then call the Set # clear () method to clear the Set.

Public Set <K> keySet ()

Returns the Set of Map key values. AbstractMap defines a member variable "transient Set <K> keySet". In JDK7, The keySet variable is modified by volatile, but it is not modified by volatile in jdk8. In the comment on the keySet variable, the method for accessing these fields is not synchronized, and volatile cannot guarantee thread security. The implementation of the keySet method is a bit interesting.

The first thought of this method is to return the Set of key values. Naturally, we can think of a simple implementation method to retrieve the key value from the Entry array and put it in the Set, similar to the following code:

1 public Set<K> keySet() {2     Set<K> ks = null;3     for (Map.Entry<K, V> entry : entrySet()) {4         ks.add(entry.getKey());5     }6     return ks;7 }

This means that the Entry array will be traversed every time the keySet method is called, and the efficiency will be greatly reduced when the data volume is large. I have to say that the JDK source code is very well written, and it does not adopt the Traversal method. If the Entry is not traversed, how can we know that a key-value pair is added to Map?

The answer is to re-implement a new custom Set within the keySet method, and rewrite the iterator method in this custom Set. Here is the key. The iterator method returns the Iterator interface, here, the Iterator iterator is implemented again, and its Iterator method is called by calling the entrySet method. The following code is used for analysis:

1 public Set <K> keySet () {2 Set <K> ks = keySet; // The defined transient Set <K> keySet 3 if (ks = null) {// if the first call is definitely null, use the following code to create a Set example 4 ks = new AbstractSet <K> () {// create a custom Set 5 public Iterator <K> iterator () {// rewrite the iterator Method 6 return new Iterator of the Set <K> () {// re-implement the Iterator interface 7 private Iterator <Entry <K, V> I = entrySet (). iterator (); // reference the Set Iterator iterator of Entry 8 9 public boolean hasNext () {10 return I. HasNext (); // key value judgment, that is, the entry Judgment 11} 12 13 public K next () {14 return I. next (). getKey (); // get the next key value, that is, take entry # getKey15} 16 17 public void remove () {18 I. remove (); // Delete the key value, that is, delete entry19} 20}; 21} 22 23 public int size () {// rewrite the Set # size Method 24 return AbstractMap. this. size (); // the value of the key is the size of the entire Map, so you can call the size method of this class. This is an internal class. The keyword this is used directly to represent this class. It should be specified to call the size method in AbstractMap. Without this, it indicates static method 25} 26 27 public boolean isEmpty () {// rewrite the Set # isEmpty Method 28 return AbstractMap. this. isEmpty (); // check whether there is a key value. This is to judge whether the Map is empty. Therefore, call the isEmpty method of this class to 29} 30 31 public void clear () {// rewrite the Set # clear method 32 using actmap. this. clear (); // clear the key value, that is, clear the Map, so call the clear method of this class to 33} 34 35 public boolean contains (Object k) {// rewrite the Set # contains method 36 return AbstractMa P. this. containsKey (k); // determines whether the Set contains data k, that is, whether the Map contains the key value. Therefore, you can call the containsKey method of this class to 37} 38 }; 39 keySet = ks; // assign this custom Set to the keySet variable. When you call the keySet method again later, you only need to return the value directly because the keySet is not null. 40} 41 return ks;

I think this is a clever implementation. Although this method focuses on the key value, it can actually be implemented with the Entry instead of traversing the Entry, at the same time, the above mentioned call the entrySet # iterator method. Here is the best practice of the template method mode. The entrySet is not implemented in AbstractMap, but is handed over to its subclass. However, for the keySet method, an "algorithm skeleton" can be implemented for it. This is the template method mode.

Public Collection <V> values ()

For the values method, you can refer to the keySet method. The two methods are similar, so we will not repeat them here to save space.

Public abstract Set <Entry <K, V> entrySet ()

An abstract method is handed over to its subclass, indicating that this method is not particularly "common ".

Public boolean equals (Object o)

Map specifies that true is returned only when the keys and values of each key-value Pair in Map are one-to-one for their equals. In the method, first judge a simple condition. If the reference is equal, true is returned directly. If the parameter o is not of the Map type, false is returned directly. If the number of two maps is different, false is returned directly. Then, traverse the Entry array and compare whether the keys and values in the Entry correspond one to one. The method is simple, but this gives us an inspiration. In the condition judgment, we should first judge the basic and complex.

Public int hashCode ()

Override the equals method of the Object class, and override hashCode is also required. AbstractMap's implementation of hashCode is to add the hashCode values of all Map. Entry (here is SimpleEntry or SimpleImmutableEntry), and the sum obtained as the hashCode value of Map.

Public String toString ()

There is nothing to say about this method. It is to extract all key-value pairs and splice them using StringBuilder.

Protected Object clone () throws CloneNotSupportedException

Implements a shortest copy. Because shortest does not copy the keySet and values variables, it prevents problems caused by two shortest copies, the Object clone method has been resolved in "the father of the ten categories-Object.

 

 

This is a public number that can add buff to programmers.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.