How to delete multiple elements in a set in Java

Source: Internet
Author: User
Tags concurrentmodificationexception

Today, I need to delete unspecified elements in the first collection from a java Collection Based on the content of the other collection. This seems very simple, but it has encountered problems. This is the question of "how to delete multiple elements in a set in Java.
 
This is the header of the method I want to write.
Private void screenBlackNameList (List <SharedBoardSmsWrapper> source, List <BlackNameListModel> blackNameList)
 
This is the case. Some data elements used for display are saved in the source set. The blacklist list is saved in the blackNameList set. We need to remove the user data from the blacklist in the source set based on the blacklist table.
 
The solution to this problem looks very simple.
 
First, I use the for each statement to delete it.
 
For (SharedBoardSmsWrapper tmpSharedBoardSmsWrapper: source ){

For (BlackNameListModel tmpBlackNameListModel: blackNameList ){
If (tmpSharedBoardSmsWrapper. getSource (). equals (tmpBlackNameListModel. getSource ())){
Source. remove (tmpSharedBoardSmsWrapper );
Break;
}

}
}
 
Very simple question! I smiled,
Test...
Unexpectedly, this code throws an exception.
Java. util. ConcurrentModificationException.
 
View JDK 6 manual
 
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. While for each, an element is deleted from the set, which causes iterator to throw ConcurrentModificationException.
 
 
It seems that only the traditional for loop is actually used!
 
For (int I = 0; I <source. size (); I ++ ){
SharedBoardSmsWrapper tmpSharedBoardSmsWrapper = source. get (I );
For (int j = 0; j <blackNameList. size (); j ++ ){
BlackNameListModel tmpBlackNameListModel = blackNameList. get (j );
If (tmpSharedBoardSmsWrapper. getSource (). equals (tmpBlackNameListModel. getSource ())){
Source. remove (tmpSharedBoardSmsWrapper );
Break;
}

}

}
 
This should be okay! Press test with confidence...
Dizzy! Why? How can I filter data?
 
After the Debug trail, we found that when the set deletes elements, the size of the set will decrease and the associated indexes will change!
What can I do? I won't be confused by such a small problem!
 
Use Iterator to delete elements in a set
 
Check the Iterator interface in the JDK manual and see that it has a remove method.
Remove
Void remove ()
Remove the last element returned by the iterator from the collection to which the iterator points (optional ). Each call to next can only be called once. If the collection point pointed to by the iterator is modified in other ways than this method, the iterator behavior is uncertain.
Throw:
UnsupportedOperationException-if the iterator does not support the remove operation.
IllegalStateException-if the next method has not been called, or the next method has been called after the last call.
 
 
 
 
 
 
Correct final code:
/**
* @ Paramsource
* @ ParamblackNameList
*/
Privatevoid screenBlackNameList (List <SharedBoardSmsWrapper> source, List <BlackNameListModel> blackNameList ){
Iterator <SharedBoardSmsWrapper> sourceIt = source. iterator ();

While (sourceIt. hasNext ()){
SharedBoardSmsWrapper tmpSharedBoardSmsWrapper = sourceIt. next ();
Iterator <BlackNameListModel> blackNameListIt = blackNameList. iterator ();
While (blackNameListIt. hasNext ()){
BlackNameListModel tmpBlackNameListModel = blackNameListIt. next ();
If (tmpSharedBoardSmsWrapper. getSource (). equals (tmpBlackNameListModel. getSource ())){
SourceIt. remove ();
Break;
}

}

}

}
 
 
Note that the next () method of the Iterator cannot be called multiple times. Otherwise, an exception is thrown.
 
 
It seems that the simplest way to delete elements in a set is to use the remove () method of Iterator!
 
 
Let's see how Iterator provided by the ArrayList class is implemented.
 
Privateclass Itr implements Iterator <E> {
/**
This is the index of an element, which is equivalent to a pointer or cursor. It is used to access the data element of the List.
* Indexofelementtobereturnedbysubsequentcalltonext.
*/
Intcursor = 0;
 
/**
* Indexofelementreturnedbymostrecentcalltonextor
* Previous. Resetto-1ifthiselementisdeletedbyacall
* Toremove.
The index of the latest element. If this element has been deleted, set it to-1.
*/
IntlastRet =-1;
 
/**
Attributes of the external class ArrayList:
Protected transient int modCount = 0;
It is used to check whether the ArrayList is modified by other threads at the same time. If they are inconsistent, a synchronization exception is thrown.
* ThemodCountvaluethattheiteratorbelievesthatthebacking
* Listshouldhave. Ifthisexpectationisviolated, theiterator
* Hasdetectedconcurrentmodification.
*/
IntexpectedModCount = modCount;
// If the cursor does not reach the List size, there are still elements.
Publicboolean hasNext (){
Returncursor! = Size ();
& Nb

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.