SoFunction
Updated on 2025-03-09

HashMap and List traversal methods and how to traverse and delete elements summary

I believe everyone is very familiar with collection traversal. Here I will summarize the traversal methods of HashMap and List, and how they can implement traversal deletion.

Here we provide a detailed explanation of the causes of the problems caused by each traversal deletion!

(I) List traversal method and how to implement traversal deletion

We create a list, and then use different methods to traverse and delete it, as follows:

List<String> list= new ArrayList<String>();
  ("zs");
  ("ls");
  ("ww");
  ("dz");

1. For loop traversal list:

 for(int i=0;i<();i++){
       if((i).equals("ls"))
       (i);
      }

This is a very common way of traversing, but using this traversal to delete elements will cause problems. The reason is that after deleting an element, the size of the list changes, and your index changes, which will cause you to miss certain elements during traversal. For example, after you delete the first element and continue to access the second element according to the index, due to the deletion, the subsequent elements move forward and think that they are actually accessing the third element. Therefore, this traversal method can be used to read elements, but is not suitable for deleting elements.

2. Enhanced for loop:

    for(String x:list){
      if(("ls"))
      (x);
    }

This is also a very common way of traversal, but using this traversal to delete elements will also cause problems. The runtime will report a ConcurrentModificationException exception.
In fact, enhanced for loop is a manifestation of java syntax sugar. If you get bytecode through decompilation, then the internal implementation of the above code is as follows:

for(Iterator<String> it = ();();){
     String s = ();
     if(("madehua")){
       (s);
     }
   }

The following explains why the ConcurrentModificationException exception is reported. Analyze the source code of Iterator, focusing on analyzing the entire calling process
Functions (hasNext and remove):

private class Itr implements Iterator&lt;E&gt; {
	    int cursor;    // index of next element to return
	    int lastRet = -1; // index of last element returned; -1 if no such
	    int expectedModCount = modCount;
 
 
	    public boolean hasNext() {
	      return cursor != size; // size is the number of elements in the set	    }
 
 
	    public E next() {
	      checkForComodification();
	      int i = cursor;
	      if (i &gt;= size)
	        throw new NoSuchElementException();
	      Object[] elementData = ;
	      if (i &gt;= )
	        throw new ConcurrentModificationException();
	      cursor = i + 1;
	      return (E) elementData[lastRet = i];
	    }
 
 
	    /* This method is not called, it is just called
	     public void remove() {
	       checkForComodification();
	       try {
	         (lastRet); // Size field minus 1
	         cursor = lastRet;
	         lastRet = -1;
	         expectedModCount = modCount;
	       } catch (IndexOutOfBoundsException ex) {
	         throw new ConcurrentModificationException();
	       }
	     }
	     */
 
 
	    final void checkForComodification() {	// Check whether the modification and the current version number are consistent. If the inconsistent, an exception will be thrown	      if (modCount != expectedModCount)
	        throw new ConcurrentModificationException();
	    }
 
 
  	}
 
 
  	// 
  	@Override public boolean remove(Object object) {
	    Object[] a = array;
	    int s = size;
	    if (object != null) {
	      for (int i = 0; i &lt; s; i++) {
	        if ((a[i])) {
	          (a, i + 1, a, i, --s - i);
	          a[s] = null; // Prevent memory leak
	          size = s;
	          modCount++;	// Core code: The version number has been modified.  In this way, when checkForComodification, the modCount value is different from expectedModCount	          return true;
	        }
	      }
	    } else {
	      for (int i = 0; i &lt; s; i++) {
	        if (a[i] == null) {
	          (a, i + 1, a, i, --s - i);
	          a[s] = null; // Prevent memory leak
	          size = s;
	          modCount++;
	          return true;
	        }
	      }
	    }
	    return false;
	  }

Next, sort out the process, and then you will find that this exception is thrown in the checkForComodification of the next method. The reason for throwing is
modCount !=expectedModCount. The modCount here refers to the number of times this list object has been modified since it has been called.
When the add or remove method is added or removed, the modCount will automatically increase or decrease; when the iterator is created, the modCount is copied to
expectedModcount, but the expectedModcount will not be automatically increased or decreased when calling the add and remove methods of the list, which will cause
The two counts are not equal, thus throwing an exception. If you understand the above execution process, you will encounter similar problems in the future, such as if the deleted one is countdown.
The second element will not encounter exceptions. You will know why.

3. Iterator traversal and delete

   Iterator<String> it = ();
   while(()){
    String x = ();
    if(("del")){
      ();
   }
  }

This method can be traversed and deleted normally. But you may see that the above code feels similar to the code implemented in the enhancement for loop. In fact, the difference is that one uses () and the other uses ().

(II) HashMap traversal deletion and how to implement traversal deletion

Let's create a hashmap first, as follows

	private static HashMap<Integer, String> map = new HashMap<Integer, String>();;
 
	public static void main(String[] args) {
		
		 for(int i = 0; i < 10; i++){ 
	      (i, "value" + i); 
	    } 
	 
	
	}

1. The first type of traversal deletion:

    for(<Integer, String> entry : ()){ 
       Integer key = (); 
       if(key % 2 == 0){ 
         ("To delete key " + key); 
         (key); 
         ("The key " + + key + " was deleted"); 
       } 

This kind of traversal deletion will still report a ConcurrentModificationException exception.

2. The second type of traversal deletion:

    Set<Integer> keySet = ();
	   for(Integer key : keySet){
	      if(key % 2 == 0){
	        ("To delete key " + key);
	        (key);
	        ("The key " + + key + " was deleted");
	      }
	   }

This kind of traversal deletion will still report a ConcurrentModificationException exception.

3. The third type of traversal deletion:

  Iterator<<Integer, String>> it = ().iterator();
    while(()){
      <Integer, String> entry = ();
      Integer key = ();
      if(key % 2 == 0){
      	 ("To delete key " + key);
      	 ();  
      	 ("The key " + + key + " was deleted");
 
      }
    }

This traversal is OK

Analyzing the above reasons, if you understand the traversal deletion of List, then you feel that there are similarities in the traversal deletion of HashMap. Let’s analyze the reasons below:
If you query the source code, the above three methods of deletion are all used to delete the key by calling the method.
After a knowledge of the key in the removeEntryForKey method, modCount will perform a self-increment operation. At this time, modCount is inconsistent with expectedModCount.
, Among the above three remove implementations, only the third iterator's remove method synchronizes the expectedModCount value and
The modCount is the same, so the iterator method does not throw exceptions. Finally, I hope that when you encounter problems, you will query the source code, and it will give you the best explanation!
---------------------
Author: de*i
Source: CSDN
Original text: /de*i/article/details/77748809
Copyright Statement: This article is an original article by the blogger. Please attach a link to the blog post when reprinting!