HashMap's 7 traversal methods and performance analysis!

In general, HashMap traversal can be divided into the following four categories:

  1. Iterator mode traversal;
  2. For Each traversal;
  3. Lambda expression traversal (JDK 1.8+);
  4. Streams API traversal (JDK 1.8+).

However, each type has different implementation methods, so the specific traversal methods can be divided into the following 7 types:

1. Use Iterator EntrySet to traverse;
2. Iterator KeySet is used for traversal;
3. Use the For Each EntrySet method to traverse;
4. Use the For Each KeySet method to traverse;
5. Use Lambda expressions to traverse;
6. Use Streams API single thread to traverse;
7. Use the Streams API to traverse in a multi-threaded manner.
Next, let's look at the specific implementation code of each traversal method.

1. Iterator EntrySet

public class HashMapTest {
    public static void main(String[] args) {
        // Create and assign HashMap
        Map<Integer, String> map = new HashMap();
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java Chinese community");
        // ergodic
        Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, String> entry = iterator.next();
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        }
    }
}

2. Iterator KeySet

public class HashMapTest {
    public static void main(String[] args) {
        // Create and assign HashMap
        Map<Integer, String> map = new HashMap();
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java Chinese community");
        // ergodic
        Iterator<Integer> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            Integer key = iterator.next();
            System.out.print(key);
            System.out.print(map.get(key));
        }
    }
}

3.ForEach EntrySet

public class HashMapTest {
    public static void main(String[] args) {
        // Create and assign HashMap
        Map<Integer, String> map = new HashMap();
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java Chinese community");
        // ergodic
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        }
    }
}

4.ForEach KeySet

public class HashMapTest {
    public static void main(String[] args) {
        // Create and assign HashMap
        Map<Integer, String> map = new HashMap();
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java Chinese community");
        // ergodic
        for (Integer key : map.keySet()) {
            System.out.print(key);
            System.out.print(map.get(key));
        }
    }
}

5.Lambda

public class HashMapTest {
    public static void main(String[] args) {
        // Create and assign HashMap
        Map<Integer, String> map = new HashMap();
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java Chinese community");
        // ergodic
        map.forEach((key, value) -> {
            System.out.print(key);
            System.out.print(value);
        });
    }
}

6.Streams API Single Thread

public class HashMapTest {
    public static void main(String[] args) {
        // Create and assign HashMap
        Map<Integer, String> map = new HashMap();
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java Chinese community");
        // ergodic
        map.entrySet().stream().forEach((entry) -> {
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        });
    }
}

7.Streams API Multithreading

public class HashMapTest {
    public static void main(String[] args) {
        // Create and assign HashMap
        Map<Integer, String> map = new HashMap();
        map.put(1, "Java");
        map.put(2, "JDK");
        map.put(3, "Spring Framework");
        map.put(4, "MyBatis framework");
        map.put(5, "Java Chinese community");
        // ergodic
        map.entrySet().parallelStream().forEach((entry) -> {
            System.out.print(entry.getKey());
            System.out.print(entry.getValue());
        });
    }
}

Security test

We divide the above traversal into four categories for testing:

  1. Iterator pattern
  2. For Loop Mode
  3. Lambda method
  4. Stream mode
    The test code is as follows.

1. Iterator mode

Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<Integer, String> entry = iterator.next();
    if (entry.getKey() == 1) {
        // delete
        System.out.println("del:" + entry.getKey());
        iterator.remove();
    } else {
        System.out.println("show:" + entry.getKey());
    }
}

Results of the above procedures:

show:0
del:1
show:2
 Test result: The iterator circularly deletes data security.

2.For cycle mode

for (Map.Entry<Integer, String> entry : map.entrySet()) {
    if (entry.getKey() == 1) {
        // delete
        System.out.println("del:" + entry.getKey());
        map.remove(entry.getKey());
    } else {
        System.out.println("show:" + entry.getKey());
    }
}

Results of the above procedures:

Test result: It is unsafe to delete data in the For loop.

3.Lambda method

map.forEach((key, value) -> {
    if (key == 1) {
        System.out.println("del:" + key);
        map.remove(key);
    } else {
        System.out.println("show:" + key);
    }
});

Results of the above procedures:

Test results: Lambda It is not safe to delete data in the loop.

Correct way to delete Lambda:

// Determine the deletion according to the key in the map
map.keySet().removeIf(key -> key == 1);
map.forEach((key, value) -> {
    System.out.println("show:" + key);
});

Results of the above procedures:

show:0
show:2
 From the above code, you can use Lambda of removeIf Deleting redundant data and then looping is a correct way to operate the collection.

4.Stream mode

map.entrySet().stream().forEach((entry) -> {
    if (entry.getKey() == 1) {
        System.out.println("del:" + entry.getKey());
        map.remove(entry.getKey());
    } else {
        System.out.println("show:" + entry.getKey());
    }
});

Execution results of the above procedures

Test results: Stream It is not safe to delete data in the loop.

The correct way of the Stream loop:

map.entrySet().stream().filter(m -> 1 != m.getKey()).forEach((entry) -> {
    if (entry.getKey() == 1) {
        System.out.println("del:" + entry.getKey());
    } else {
        System.out.println("show:" + entry.getKey());
    }
});

Results of the above procedures:

show:0
show:2

As can be seen from the above code, you can use the filter in Stream to filter out useless data, and then traverse it is a safe way to operate the collection.

Summary

We cannot use set maps in traversal Remove () to delete data, which is a non secure operation mode, but we can use the iterator of the iterator Remove () method to delete data, which is a safe way to delete a collection. Similarly, we can use the removeIf in Lambda to delete data in advance, or use the filter in Stream to filter out the data to be deleted for a loop. This is safe. Of course, we can also delete data before the for loop. Traversal is also thread safe.

summary

In this article, we talked about the four types of HashMap traversal methods (iterator, for, Lambda, stream), and the specific seven traversal methods. Except for the parallel loop of Stream, the performance of the other traversal methods is not different, but from the perspective of simplicity and elegance, Lambda and Stream are undoubtedly the most suitable traversal methods. In addition, we also tested four types of traversal results in terms of "security". In terms of security, we should use iterators provided by iterators The remove() method is used to delete. This is a safe way to delete the collection during traversal, or to filter the data to be deleted using the filter in the Stream and then cycle.
In general, the seven methods provided in this article are certainly not the most comprehensive. I want to give readers more choices when using HashMap. However, the choice of the writing method should be considered comprehensively in terms of performance, security, JDK version of the use environment, elegance and readability. Finally, you are welcome to add and leave a message in the comment area and write your thoughts.

Detailed link:

Tags: Java Mybatis programming language

Posted by bookbuyer2000 on Mon, 19 Sep 2022 21:21:02 +0300