9

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

}

}
Isuru
  • 3,818
  • 13
  • 49
  • 64

2 Answers2

20

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.

Eric Jablow
  • 7,874
  • 2
  • 22
  • 29
5

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.

Community
  • 1
  • 1
Boris the Spider
  • 59,842
  • 6
  • 106
  • 166