Home > Java > javaTutorial > body text

How to delete elements during List or Map traversal in Java

高洛峰
Release: 2017-01-22 16:25:46
Original
1885 people have browsed it

There are many ways to traverse and delete elements in a List or Map, and problems will occur when used improperly. Let’s learn more through this article.

1. Delete elements during List traversal

Use index subscript traversal

Example: Delete 2 in the list

public static void main(String[] args) {
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);
   
  for (int i = 0; i < list.size(); i++) {
   if(2 == list.get(i)){
    list.remove(i);
   }
   System.out.println(list.get(i));
  }
   
  System.out.println("list=" + list.toString());
   
 }
Copy after login

Output result:

1
2
3
4
list=[1, 2, 3, 4]
Copy after login

Problem:

The result shows only delete One 2 was deleted, and the other 2 was omitted. The reason is: after deleting the first 2, the number of elements in the set was reduced by 1, and the subsequent elements were moved forward by 1 position, resulting in the second 2 being omitted. .

Use For loop traversal

Example:

public static void listIterator2(){
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);
   
  for (int value : list) {
   if(2 == value){
    list.remove(value);
   }
   System.out.println(value);
  }
   
  System.out.println("list=" + list.toString());
   
 }
Copy after login


Result:

Exception in thread "main" 1
2
java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
 at java.util.ArrayList$Itr.next(Unknown Source)
 at test.ListIterator.listIterator2(ListIterator.java:39)
 at test.ListIterator.main(ListIterator.java:10)
Copy after login

Description:

Description of ConcurrentModificationException in jdk:

public class ConcurrentModificationException extends

RuntimeException This exception is thrown when a method detects concurrent modification of an object, but does not allow such modification.

For example, when one thread iterates over a Collection, another thread is usually not allowed to linearly modify the Collection. Often in these cases, the results of the iteration are indeterminate. Some iterator implementations (including all generic collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that perform this operation are called fail-fast iterators because the iterator fails completely quickly without risking arbitrary unspecified behavior at some time in the future.

Note: This exception will not always indicate that the object has been modified concurrently by different threads. An object may throw this exception if a single thread issues a sequence of method calls that violates the object's contract. For example, if a thread directly modifies a collection while iterating over it using a fail-fast iterator, the iterator will throw this exception.

Note: The fail-fast behavior of iterators is not guaranteed because, in general, it is not possible to make any hard guarantees about whether unsynchronized concurrent modifications will occur. Fail-fast operations throw a ConcurrentModificationException on a best-effort basis. Therefore, it is a mistake to write a program that relies on this exception to improve the correctness of such operations. The correct approach is: ConcurrentModificationException should only be used to detect bugs.

For each in Java actually uses an iterator for processing. The iterator does not allow the collection to be deleted during the use of the iterator. So it caused the iterator to throw ConcurrentModificationException.

The correct way

Example:

public static void listIterator3(){
  List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(2);
  list.add(3);
  list.add(4);
   
  Iterator<Integer> it = list.iterator();
  while (it.hasNext()){
   Integer value = it.next();
   if (2 == value) {
    it.remove();
   }
    
   System.out.println(value);
  }
   
  System.out.println("list=" + list.toString());
 }
Copy after login

Result:

1
2
2
3
4
list=[1, 3, 4]
Copy after login

2. Deleting elements during Map traversal

Example of the correct approach:

public static void main(String[] args) {
 HashMap<String, String> map = new HashMap<String, String>();
 map.put("1", "test1");
 map.put("2", "test2");
 map.put("3", "test3");
 map.put("4", "test4");
  
 //完整遍历Map
 for (Entry<String, String> entry : map.entrySet()) {
  System.out.printf("key: %s value:%s\r\n", entry.getKey(), entry.getValue());
 }
  
 //删除元素
 Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
 while(it.hasNext())
 {
  Map.Entry<String, String> entry= it.next();
  String key= entry.getKey();
  int k = Integer.parseInt(key);
  if(k%2==1)
  {
   System.out.printf("delete key:%s value:%s\r\n", key, entry.getValue());
   it.remove();
  }
 }
  
 //完整遍历Map
 for (Entry<String, String> entry : map.entrySet()) {
  System.out.printf("key: %s value:%s\r\n", entry.getKey(), entry.getValue());
 }
}
Copy after login


Result:

key: 1 value:test1
key: 2 value:test2
key: 3 value:test3
key: 4 value:test4
delete key:1 value:test1
delete key:3 value:test3
key: 2 value:test2
key: 4 value:test4
Copy after login

Note

But there are also things we need to pay attention to about the remove() method of iterator:

Every time the iterator.next() method is called, the remove() method can only be called once.

Before calling the remove() method, the next() method must be called once.

Description of the remove() method in JDK-API:

void remove() removes the last element returned by the iterator from the collection pointed to by the iterator (optional operation). This method can only be called once per call to next. The behavior of an iterator is undefined if the collection pointed to by the iterator is modified while it is being iterated in a manner other than by calling this method.

Throws: UnsupportedOperationException - if the iterator does not support the remove operation. IllegalStateException - if the next method has not been called, or the remove method has been called since the last call to the next method.

Summary

The above is all about deleting elements during the traversal process of List and Map. I hope the content of this article can bring some help to everyone's study or work. If you have any questions, you can leave a message to communicate.

For more articles on how to delete elements during List or Map traversal in Java, please pay attention to the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template