In Java, sometimes we need to delete the data in the list that conforms to a certain business, but if we do not understand the mechanism in it, it is easy to fall into the "trap", leading to omissions or program exceptions. This article describes the problem using code examples.
1. Index subscript Traversal
Let's look at the sample code:
View Source
Print?
1 |
public class ListRemoveTest { |
3 |
public
static void main(String[] args) {
|
4 |
List<Integer> list =
new ArrayList<Integer>();
|
11 |
for
( int i =
0 ; i < list.size(); i++) {
|
12 |
if
( 2 == list.get(i)) {
|
15 |
System.out.println(list.get(i));
|
17 |
System.out.println( "Final result ="
+ list.toString()); |
The code runs as follows:
1
2
3
4
Final result = [1, 2, 3, 4]
We want to delete an element equal to 2, but the result shows that only one 2 is deleted, and the other 2 is omitted because after the first 2 is deleted, the number of elements in the set is reduced by 1, and the elements behind the set are moved forward by 1, leading to the omission of the second 2.
2. Use the for loop Traversal method
View Source
Print?
1 |
public class ListRemoveTest { |
3 |
public
static void main(String[] args) {
|
4 |
List<Integer> list =
new ArrayList<Integer>();
|
11 |
for
(Integer value : list) { |
15 |
System.out.println(value);
|
17 |
System.out.println( "Final result ="
+ list.toString()); |
Program running result:
1
2
Exception in thread "main" java. util. concurrentmodificationexception
At java. util. effecactlist $ itr. checkforcomodification (effecactlist. Java: 372)
At java. util. abstractlist $ itr. Next (abstractlist. Java: 343)
At listremovetest. Main (listremovetest. Java: 32)
The running result shows that the program throws concurrentmodificationexception.
The exception is described in the jdk api:
Public class concurrentmodificationexception extends runtimeexception this exception is thrown when the method detects concurrent object modifications but does not allow such modifications.
For example, when a thread iterates over a collection, it usually does not allow another thread to linearly modify the collection. In these cases, the iteration results are usually uncertain. If this behavior is detected, some iterator implementations (including all common collection implementations provided by JRE) may choose to throw this exception. The iterator that executes this operation is called the fast failure iterator, because the iterator quickly fails completely without the risk of any uncertain behavior at a certain time in the future.
Note that this exception does not always indicate that the object has been modified concurrently by different threads. If a single thread sends a method call sequence that violates the object protocol, the object may throw this exception. For example, if the thread uses the quick failure iterator to directly modify the collection when it iterates on the collection, the iterator will throw this exception.
Note: The Fast failure behavior of the iterator cannot be guaranteed, because in general, it is impossible to make any hard guarantee for non-synchronous concurrent modifications. The quick failed operation will throw concurrentmodificationexception as much as possible. Therefore, writing a program dependent on this exception to improve the correctness of such operations is an incorrect practice. The correct practice is: concurrentmodificationexception should only be used to detect bugs.
In Java, for each actually uses iterator for processing. Iterator does not allow the collection to be deleted during use of iterator. Therefore, the iterator throws concurrentmodificationexception.
.
3. DeleteCorrect practice
View Source
Print?
1 |
public class ListRemoveTest { |
3 |
public
static void main(String[] args) {
|
4 |
List<Integer> list =
new ArrayList<Integer>();
|
11 |
Iterator<Integer> it = list.iterator();
|
13 |
Integer value = it.next();
|
17 |
System.out.println(value);
|
19 |
System.out.println( "Final result ="
+ list.toString()); |
Output result:
1
2
2
3
4
Final result = [1, 3, 4]
We can see that both 2 are deleted, and 3, 4 are completely correct.
But for the remove () method of iterator, we also need to pay attention to the following points:
1. Each time you call the iterator. Next () method, you can only call the remove () method once.
2. You must call the next () method once before calling the remove () method.
The following is a description of the remove () method in the JDK-API:
Void
Remove()
Removes the last element returned by the iterator from the set to which the iterator points (optional ). Each callNextThis method can be called only once. If the set pointed to by the iterator is modified in other ways than this method, the iterator behavior is unclear.
Throw:UnsupportedOperationException
-If the iterator is not supported
RemoveOperation.IllegalStateException
-If you have not calledNextMethod, or the last call
NextThe method has been called.RemoveMethod.
Reprinted: http://wangchongan.com/articles/java-list-remove-function.html