Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception in thread "main" java.util.ConcurrentModificationException

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);

}

}
like image 718
Isuru Avatar asked May 11 '13 18:05

Isuru


People also ask

How do I fix Java Util ConcurrentModificationException?

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 Java Util ConcurrentModificationException?

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.

How can we avoid ConcurrentModificationException in a single threaded environment?

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.


2 Answers

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.

like image 173
Eric Jablow Avatar answered Oct 19 '22 00:10

Eric Jablow


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.

like image 44
Boris the Spider Avatar answered Oct 18 '22 23:10

Boris the Spider