This blog mainly explains how to use HashMap, Hashtable, LinkedHashMap, TreeMap and the differences between the four implementation classes of Map interface.

Note: The code in this article uses JDK version 1.8.0_191

It is important to note that the Map interface is a separate interface and does not inherit the Collection interface:

public interface Map<K.V> {... }Copy the code

1. Use a HashMap

HashMap is the most commonly used implementation class of the Map interface. It stores key-value pairs. A HashMap does not guarantee the order of elements but guarantees that keys must be unique.

The code declaration for the HashMap class looks like this:

public class HashMap<K.V> extends AbstractMap<K.V>
    implements Map<K.V>, Cloneable.Serializable {... }Copy the code

1.1 Adding Elements

There are three ways to add elements using HashMap:

  1. put
  2. putIfAbsent
  3. putAll

First let’s look at how the put() method is used:

HashMap<String, String> platformMap = new HashMap<>();

// Add elements
System.out.println(platformMap.put("cnblogs.com".Blog Park));
System.out.println(platformMap.put("juejin.im"."Nuggets"));
System.out.println(platformMap.put("map.weixin.qq.com"."Wechat Official Account"));
System.out.println(platformMap.put("zwwhnly.com"."Personal Blog"));

// Add the duplicate Key, failed to add the duplicate Key, but the corresponding Value of the Key is updated
// The code does not return an error, but instead returns a Value corresponding to the existing Key
System.out.println(platformMap.put("zwwhnly.com"."Personal Blog"));
Copy the code

The output from the above code run is:

null

null

null

null

Personal blog

Debugging the code will also find that the platformMap has only four elements, and the order of the elements is different from the order in which they were added:

Note that the last line of code platformmap. put(“zwwhnly.com”, “personal blog “) returns” personal blog “, which is the existing Key:zwwhnly.com, corresponding to the Value.

Simply change this to:

System.out.println(platformMap.put("zwwhnly.com".Personal Blog 2));
Copy the code

Run the code again and find that the output is the same, and the platformMap element has four elements, but the content of the platformMap element has changed:

If you do not want Value to be overwritten when Key is present, you can change the code to:

System.out.println(platformMap.putIfAbsent("zwwhnly.com".Personal Blog 2));
Copy the code

In addition, HashMap provides a putAll() method to add elements in batches as follows:

HashMap<String, String> platformMap = new HashMap<>();

HashMap<String, String> majorPlatfromMap = new HashMap<>();

// Add elements
majorPlatfromMap.put("cnblogs.com".Blog Park);
majorPlatfromMap.put("juejin.im"."Nuggets");

HashMap<String, String> otherPlatformMap = new HashMap<>();

otherPlatformMap.put("map.weixin.qq.com"."Wechat Official Account");
otherPlatformMap.put("zwwhnly.com"."Personal Blog");

otherPlatformMap.put("cnblogs.com"."Blogland 2");

platformMap.putAll(majorPlatfromMap);
platformMap.putAll(otherPlatformMap);
Copy the code

Note that since majorPlatfromMap and otherPlatformMap have the same Key: cnblogs.com, the Value of the final platformMap with Key “cnblogs.com” is “Blogpark 2”, as shown below:

1.2 Obtaining Elements

There are two ways to get elements using HashMap:

  1. get()
  2. getOrDefault()

Let’s first look at how the get() method works:

System.out.println(platformMap.get("cnblogs.com"));
System.out.println(platformMap.get("csdn.com"));
Copy the code

Output result:

Blog garden

null

If you want to set the default value when key is not present, use getOrDefault() :

System.out.println(platformMap.getOrDefault("csdn.com"."CSDN"));
Copy the code

The output of this code is CSDN.

1.3 Obtaining the number of set elements

Get the number of HashMap elements as follows:

System.out.println("The number of platformMap elements is:" + platformMap.size());
Copy the code

1.4 Deleting Elements

Using HashMap to delete elements has the following two overloads:

public V remove(Object key) {
    Node<K,V> e;
    return (e = removeNode(hash(key), key, null.false.true)) = =null ?
        null : e.value;
}

@Override
public boolean remove(Object key, Object value) {
    return removeNode(hash(key), key, value, true.true) != null;
}
Copy the code

The usage method is as follows:

System.out.println(platformMap.remove("zwwhnly.com"));
System.out.println(platformMap.remove("zwwhnly.com"));
System.out.println(platformMap.remove("map.weixin.qq.com"."Wechat Official Account"));
System.out.println(platformMap.remove("juejin.im".Blog Park));
Copy the code

The output of the above code is:

Personal blog

null

true

false

1.5 Modifying Elements

Using HashMap to modify elements has the following two overloads:

@Override
public boolean replace(K key, V oldValue, V newValue) {
    Node<K,V> e; V v;
    if((e = getNode(hash(key), key)) ! =null&& ((v = e.value) == oldValue || (v ! =null && v.equals(oldValue)))) {
        e.value = newValue;
        afterNodeAccess(e);
        return true;
    }
    return false;
}

@Override
public V replace(K key, V value) {
    Node<K,V> e;
    if((e = getNode(hash(key), key)) ! =null) {
        V oldValue = e.value;
        e.value = value;
        afterNodeAccess(e);
        return oldValue;
    }
    return null;
}
Copy the code

The usage method is as follows:

System.out.println(platformMap.replace("cnblogs.com"."Blog garden: https://www.cnblogs.com/zwwhnly/"));
System.out.println(platformMap.replace("juejin.im"."Nuggets".The nuggets: "https://juejin.cn/user/3245414056985831"));
Copy the code

The output of the above code is:

Blog garden

true

1.6 Check whether the set is empty

To determine whether a HashMap is empty, use the following method:

System.out.println("isEmpty:" + platformMap.isEmpty());
Copy the code

1.7 Traverse elements (Often asked in interviews)

There are four main ways to traverse a HashMap element:

  1. Use keySet to get all the keys and then iterate over them
  2. Get all the elements using map. entrySet, and then iterate through them using iterator
  3. Use map. entrySet to get all the elements and then use a foreach loop to iterate through them
  4. Obtain all values by using values. This method cannot iterate over keys

Platformmap.entryset () returns a Set whose element type is map.Entry

:
,v>

public Set<Map.Entry<K,V>> entrySet() {
    Set<Map.Entry<K,V>> es;
    return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
Copy the code

The usage method is as follows:

System.out.println("Method 1: Traversal using keySet");
for (String key : platformMap.keySet()) {
    System.out.println("Key:" + key + ",Value:" + platformMap.get(key));
}

System.out.println();
System.out.println("Method 2: Iterator through map. entrySet");
Iterator<Map.Entry<String, String>> iterator = platformMap.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String, String> entry = iterator.next();
    System.out.println("Key:" + entry.getKey() + ",Value:" + entry.getValue());
}

System.out.println();
System.out.println("Method 3: Iterator through map. entrySet");
for (Map.Entry<String, String> entry : platformMap.entrySet()) {
    System.out.println("Key:" + entry.getKey() + ",Value:" + entry.getValue());
}

System.out.println();
System.out.println("Method 4: Use values to iterate. Keys cannot be iterated using this method.");
for (String value : platformMap.values()) {
    System.out.println(value);
}
Copy the code

1.8 Clearing collections

Clearing all elements in a HashMap is done as follows:

platformMap.clear();
Copy the code

1.9 Complete sample code

The complete code for the points explained above is as follows:

package collection;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapTest {
    public static void main(String[] args) {
        HashMap<String, String> platformMap = new HashMap<>();

        HashMap<String, String> majorPlatfromMap = new HashMap<>();

        // Add elements
        majorPlatfromMap.put("cnblogs.com".Blog Park);
        majorPlatfromMap.put("juejin.im"."Nuggets");

        HashMap<String, String> otherPlatformMap = new HashMap<>();

        otherPlatformMap.put("map.weixin.qq.com"."Wechat Official Account");
        otherPlatformMap.put("zwwhnly.com"."Personal Blog");

        platformMap.putAll(majorPlatfromMap);
        platformMap.putAll(otherPlatformMap);

        System.out.println(platformMap.get("cnblogs.com"));
        System.out.println(platformMap.get("csdn.com"));
        System.out.println(platformMap.getOrDefault("csdn.com"."CSDN"));

        System.out.println("The number of platformMap elements is:" + platformMap.size());

        System.out.println(platformMap.remove("zwwhnly.com"));
        System.out.println(platformMap.remove("zwwhnly.com"));
        System.out.println(platformMap.remove("map.weixin.qq.com"."Wechat Official Account"));
        System.out.println(platformMap.remove("juejin.im".Blog Park));

        System.out.println(platformMap.replace("cnblogs.com"."Blog garden: https://www.cnblogs.com/zwwhnly/"));
        System.out.println(platformMap.replace("juejin.im"."Nuggets".The nuggets: "https://juejin.cn/user/3245414056985831"));

        System.out.println("isEmpty:" + platformMap.isEmpty());

        System.out.println("Method 1: Traversal using keySet");
        for (String key : platformMap.keySet()) {
            System.out.println("Key:" + key + ",Value:" + platformMap.get(key));
        }

        System.out.println();
        System.out.println("Method 2: Iterator through map. entrySet");
        Iterator<Map.Entry<String, String>> iterator = platformMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            System.out.println("Key:" + entry.getKey() + ",Value:" + entry.getValue());
        }

        System.out.println();
        System.out.println("Method 3: Iterator through map. entrySet");
        for (Map.Entry<String, String> entry : platformMap.entrySet()) {
            System.out.println("Key:" + entry.getKey() + ",Value:" + entry.getValue());
        }

        System.out.println();
        System.out.println("Method 4: Use values to iterate. Keys cannot be iterated using this method.");
        for (String value : platformMap.values()) {
            System.out.println(value);
        }

        platformMap.clear();
        System.out.println("isEmpty:"+ platformMap.isEmpty()); }}Copy the code

The output is:

Blog garden

null

CSDN

The number of platformMap elements is: 4

Personal blog

null

true

false

Blog garden

true

isEmpty:false

Method 1: Use keySet to traverse

Key:cnblogs.com,Value: blog park: www.cnblogs.com/zwwhnly/

Key: Juejin. Im,Value: Nuggets: juejin.cn/user/324541…

Method 2: Use map. entrySet to iterate through iterator

Key:cnblogs.com,Value: blog park: www.cnblogs.com/zwwhnly/

Key: Juejin. Im,Value: Nuggets: juejin.cn/user/324541…

Method 3: Use map. entrySet to iterate through iterator

Key:cnblogs.com,Value: blog park: www.cnblogs.com/zwwhnly/

Key: Juejin. Im,Value: Nuggets: juejin.cn/user/324541…

Method 4: The Key cannot be traversed by values

Blog Park: www.cnblogs.com/zwwhnly/

The Denver nuggets: juejin. Cn/user / 324541…

isEmpty:true

2. The Hashtable

Hashtable is also an implementation class for the Map interface, and it is notable that its methods are synchronous, i.e., thread-safe.

public synchronized int size() {
    return count;
}

public synchronized boolean isEmpty() {
    return count == 0;
}
Copy the code

The code declaration for the HashTable class looks like this:

public class Hashtable<K.V>
    extends Dictionary<K.V>
    implements Map<K.V>, Cloneable.java.io.Serializable {{... }Copy the code

As you can see from the above code, the base class of Hashtable is Dictionary, and the base class of HashMap is AbstractMap.

The HashTable class is used in much the same way as the HashMap class, just by changing the code in the declaration:

Hashtable<String, String> platformMap = new Hashtable<>();
Hashtable<String, String> majorPlatfromMap = new Hashtable<>();
Hashtable<String, String> otherPlatformMap = new Hashtable<>();
Copy the code

3. Use LinkedHashMap

LinkedHashMap is also an implementation class of the Map interface. Compared to HashMap, LinkedHashMap uses a linked list, thus ensuring the insertion order of elements, i.e. FIFO(First Input, First Output).

The code declaration for the LinkedHashMap class looks like this:

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>
{
	......
}
Copy the code

As you can also see from the above code, the LinkedHashMap class inherits from the HashMap class.

The LinkedHashMap class is used in much the same way as HashMap, just by modifying the code in the declaration:

LinkedHashMap<String, String> platformMap = new LinkedHashMap<>();
LinkedHashMap<String, String> majorPlatfromMap = new LinkedHashMap<>();
LinkedHashMap<String, String> otherPlatformMap = new LinkedHashMap<>();
Copy the code

4. Use TreeMap

TreeMap is also the implementation class of the Map interface. It is worth noting that elements in TreeMap are ordered, and the default sort is ascending by lexicographical order for keys.

The code declaration for the TreeMap class looks like this:

public class TreeMap<K.V>
    extends AbstractMap<K.V>
    implements NavigableMap<K.V>, Cloneable.java.io.Serializable
{... }Copy the code

The TreeMap class is used in much the same way as HashMap, just by modifying the code in the declaration:

TreeMap<String, String> platformMap = new TreeMap<>();
TreeMap<String, String> majorPlatfromMap = new TreeMap<>();
TreeMap<String, String> otherPlatformMap = new TreeMap<>();
Copy the code

5. The difference between HashMap, Hashtable, LinkedHashMap, TreeMap

5.1 similarities

1)HashMap, Hashtable, LinkedHashMap, TreeMap all implement Map interface

2) The uniqueness of Key is guaranteed by all four methods, that is, Key repetition is not allowed

5.2 the difference between

5.2.1 sorting

The HashMap does not guarantee the order of elements

Hashtable does not guarantee the order of elements

LinkHashMap ensures that fifOS are sorted by insertion order

TreeMap guarantees the order of elements and supports custom collation rules

Empty words without proof, on the code to see the effect:

HashMap<String, String> hashMap = new HashMap<>();
Hashtable<String, String> hashtable = new Hashtable<>();
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
TreeMap<String, String> treeMap = new TreeMap<>();

String[] letterArray = new String[]{"B"."A"."D"."C"."E"};
for (String letter : letterArray) {
    hashMap.put(letter, letter);
    hashtable.put(letter, letter);
    linkedHashMap.put(letter, letter);
    treeMap.put(letter, letter);
}

System.out.println("HashMap(I don't guarantee order):" + hashMap);
System.out.println("Hashtable(I don't guarantee order):" + hashtable);
System.out.println("LinkedHashMap(I guarantee the order in which elements are inserted):" + linkedHashMap);
System.out.println("TreeMap(I guarantee the order of elements by sorting rules):" + treeMap);
Copy the code

The output of the above code is:

{A=A, B=B, C=C, D=D, E=E}

{A=A, E=E, D=D, C=C, B=B}

LinkedHashMap(I guarantee the order in which elements are inserted):{B=B, A=A, D=D, C=C, E=E}

TreeMap(I guarantee the order of elements by sorting rules):{A=A, B=B, C=C, D=D, E=E}

5.2.2 null values

HashMap, LinkedHashMap allow adding null values (both Key and Value are allowed), so the following code is legal:

HashMap<String, String> hashMap = new HashMap<>();
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();

hashMap.put(null.null);
linkedHashMap.put(null.null);
Copy the code

TreeMap does not allow null values for keys, but does allow null values for values, so the following code is legal:

TreeMap<String, String> treeMap = new TreeMap<>();

treeMap.put("cnblogs.com".null);
Copy the code

But the treeMap. Put (null, null); Will lead to Java. Lang. NullPointerException:

Hashtable doesn’t allow null values (Key and Value are not allowed), add a null Value thrown when the Java. Lang. NullPointerException.

Hashtable<String, String> hashtable = new Hashtable<>();

hashtable.put("cnblogs.com".null);
hashtable.put(null.null);
Copy the code

Run the above code and the following error message is displayed:

5.2.3 Thread Safety

HashMap, LinkedHashMap, TreeMap are not thread-safe.

Hashtable is thread-safe, which has the advantage of being less efficient than HashMap in theoretical situations.

So if there is no thread-safety requirement, HashMap is recommended.

5.2.4 inheritance

The parent class of Hashtable is Dictionary.

The parent of HashMap is AbstractMap.

LinkedHashMap’s parent class is HashMap, and HashMap’s parent class is AbstractMap, so LinkedHashMap also descends from AbstractMap.

TreeMap’s parent class is AbstractMap.

6. Two ways to sort TreeMap

TreeMap’s default sorting rule is to sort keys in ascending dictionary order.

Let’s look at an example of TreeMap storing a String:

TreeMap<String, String> treeMap = new TreeMap<>();

String[] letterArray = new String[]{"B"."A"."D"."C"."E"};
for (String letter : letterArray) {
    treeMap.put(letter, letter);
}

for (String key : treeMap.keySet()) {
    System.out.println("key:" + key + ",Value:" + treeMap.get(key));
}
Copy the code

Output result:

key:A,Value:A

key:B,Value:B

key:C,Value:C

key:D,Value:D

key:E,Value:E

So what’s the sort of element we put into TreeMap if it’s our own reference type?

With that in mind, create a new Student class like this:

package collection;

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge(a) {
        return age;
    }

    public void setAge(int age) {
        this.age = age; }}Copy the code

Then add the following validation code:

TreeMap<Student, Student> studentTreeMap = new TreeMap<>();

Student student1 = new Student("zhangsan".20);
Student student2 = new Student("lisi".22);
Student student3 = new Student("wangwu".24);
Student student4 = new Student("zhaoliu".26);

Student student5 = new Student("zhangsan".22);

studentTreeMap.put(student1, student1);
studentTreeMap.put(student2, student2);
studentTreeMap.put(student3, student3);
studentTreeMap.put(student4, student4);
studentTreeMap.put(student5, student5);

for (Student student : studentTreeMap.keySet()) {
    System.out.println("name:" + student.getName() + ",age:" + student.getAge());
}
Copy the code

Run the code to see the effect, only to find the following error:

Why is that?

This is because we haven’t defined any sort rules for the Student class, and TreeMap said, “I don’t know how to sort this, but I’ll throw an exception.”

How do you solve it? There are two ways:

  1. Natural ordering
  2. Comparator sort

6.1 Natural Ordering

Natural sorting is implemented by having the Student class implement the interface Comparable and rewrite the interface’s method compareTo, which defines the sorting rules.

package collection;

public class Student implements Comparable<Student> {
    // Omit other code

    @Override
    public int compareTo(Student o) {
        return 0; }}Copy the code

The compareTo() method generated by default using IDEA is shown above.

This method is executed when the add() method is used to add elements to determine their location.

If 0 is returned, the two elements are the same and only the first element is retained

If the return value is greater than 0, the element is placed after the specified element O in the argument

If the return value is less than 0, the element is placed before the specified element O in the argument

So if you run the validation code without making any changes to the compareTo() method, you’ll find only one element in the collection:

name:zhangsan,age:20

Then change the logic of the compareTo() method to:

@Override
public int compareTo(Student o) {
    // The collation rules are described as follows
    // The names are sorted by length, with short names in the front and long names in the back
    // If the names are of the same length, compare strings in lexicographical order
    // If the names are exactly the same, the younger ones go first and the older ones go second

    int orderByNameLength = this.name.length() - o.name.length();
    int orderByName = orderByNameLength == 0 ? this.name.compareTo(o.name) : orderByNameLength;
    int orderByAge = orderByName == 0 ? this.age - o.age : orderByName;

    return orderByAge;
}
Copy the code

Run the validation code again, and the output looks like this:

name:lisi,age:22

name:wangwu,age:24

name:zhaoliu,age:26

name:zhangsan,age:20

name:zhangsan,age:22

6.2 Comparator sorting

Comparator sorting is implemented by creating a new Comparator class that inherits the interface Comparator and overrides the interface’s Compare() method.

Note: To use this approach, the Student class does not need to implement the interface Comparable, let alone override the interface’s method compareTo.

package collection;

import java.util.Comparator;

public class StudentComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        // The collation rules are described as follows
        // The names are sorted by length, with short names in the front and long names in the back
        // If the names are of the same length, compare strings in lexicographical order
        // If the names are exactly the same, the younger ones go first and the older ones go second

        int orderByNameLength = o1.getName().length() - o2.getName().length();
        int orderByName = orderByNameLength == 0 ? o1.getName().compareTo(o2.getName()) : orderByNameLength;
        int orderByAge = orderByName == 0 ? o1.getAge() - o2.getAge() : orderByName;

        returnorderByAge; }}Copy the code

StudentTreeSet = studentTreeSet = studentTreeSet = studentTreeSet = studentTreeSet

TreeMap<Student, Student> studentTreeMap = new TreeMap<>(new StudentComparator());
Copy the code

The output is exactly the same as with natural sorting.

7. Source code and reference

Four ways to traverse a HashMap

TreeMap sorted

List,Set, Map, etc.