When I run the below code, I get an exception. I searched but couldn't find any solution.
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at com.aybits.software.linkgrabber.Grabber.main(Grabber.java:45)
Line number 45 is for(String linkFromCollection : linksList){
public class Grabber {
static String url;
Document doc;
static Set<String> linksList = new HashSet<String>();
String matchingString ="java2s.com/Code";
static boolean isCrawling = true;
static int STOP_WATCH = 0;
public Grabber(String url){
Grabber.url = url;
}
public void grabLinks(String urlToCrawl) throws IOException{
doc = Jsoup.connect(urlToCrawl).timeout(20 * 1000).get();
Elements links = doc.select("a[href]");
for (Element link : links) {
//print(" * a: <%s> (%s)", link.attr("abs:href"), trim(link.text(), 35));
if(link.attr("abs:href").toString().contains(matchingString)){
if(!linksList.contains(link.attr("abs:href").toString())){
System.out.println("Added - " + link.attr("abs:href"));
linksList.add(link.attr("abs:href").toString());
}
}
}
}
public static void main(String[] args) throws IOException {
Grabber app = new Grabber("http://java2s.com");
app.grabLinks(url);
while(isCrawling){
for(String linkFromCollection : linksList){
app.grabLinks(linkFromCollection);
if(linksList.contains(linkFromCollection)){
STOP_WATCH += 5;
System.out.println("STOP_WATCH IS " + STOP_WATCH);
}else{
STOP_WATCH -= 1;
System.out.println("STOP_WATCH IS " + STOP_WATCH);
}
if(STOP_WATCH >= 100){
isCrawling = false;
System.out.println("STOP_WATCH IS " + STOP_WATCH);
}
}
}
ICVSWrite writer = new ICVSWrite();
String[] strArray = (String[]) linksList.toArray();
writer.write(strArray);
}
}
How do you fix Java's ConcurrentModificationException? There are two basic approaches: Do not make any changes to a collection while an Iterator loops through it. If you can't stop the underlying collection from being modified during iteration, create a clone of the target data structure and iterate through the clone.
What Causes ConcurrentModificationException. The ConcurrentModificationException generally occurs when working with Java Collections. The Collection classes in Java are very fail-fast and if they are attempted to be modified while a thread is iterating over it, a ConcurrentModificationException is thrown.
Using Loops: We used the Iterator remove() method instead of that we can use a for loop to avoid ConcurrentModificationException in a Single-threaded environment. If we add any extra objects then we can ensure that our code takes care of them.
The line
linksList.add(link.attr("abs:href").toString());
modifies the linksList
collection while you are iterating over it. The next time through the for
loop in main
, Java calls next
on the collection, sees that the collection has been modified, and throws the exception.
When you are doing an enhanced for
loop, you cannot add to or remove from the collection.
You cannot call add
on a Collection
while looping over it. Here:
for (Element link : links) {
if(...){
if(...){
...
linksList.add(link.attr("abs:href").toString());
^^^ <- here
}
}
}
You call grabLinks
method from your main
method from within a loop over linksList
:
for(String linkFromCollection : linksList) {
app.grabLinks(linkFromCollection);
You have to add your items to another Collection
and then copy them over after.
What had me puzzled for a little while was why the exception was coming from a HashMap
as I had assumed that linksList
was a List
- obviously it's a Set
. Not the best name in the world.
This should help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With