如何在添加hashset值时修改迭代器

时间:2014-10-07 10:28:56

标签: java iterator hashset

我已经编写了代码,用于在java中使用selenium webdriver找出网站中存在的断开的链接。在启动不同的网址时,HashSet中会添加链接。我试图从HashSet读取添加的URL,它会在一段时间后停止执行。发生这种情况是因为迭代器仍然存在,因为它甚至添加了HashSet的新链接。我希望对HashSet中存在的所有链接继续执行。 [我试图将Set转换为数组,但重复的链接正在执行多次。]

public Set<String> unique_links;
HashMap<String, String> result;
Set<String> finalLinkSet = new HashSet<>();
Set<String> hs = new HashSet<>();
Set<String> uniqueLinkSet = new HashSet<>();
// String[] finalLinkArray;
String[] finalLinkArray;
boolean isValid = false;
FileWriter fstream;
BufferedWriter out;
int count = 1;
int FC = 0;
Set<String> secondaryset = new HashSet<>();

// String Responsecode = null;

@Test
public void LinkTesting() throws IOException, RowsExceededException,
        WriteException {

    w.manage().deleteAllCookies();
    unique_links = new HashSet<String>();
    w.get("http://www.skyscape.com");

    ArrayList<WebElement> urlList = new ArrayList<WebElement>();
    urlList = (ArrayList<WebElement>) w.findElements(By.tagName("a"));

    setFinalLinkSet(getUniqueList(urlList));


    for(Iterator<String> i = finalLinkSet.iterator(); i.hasNext(); ) {

    System.out.println(finalLinkSet.size());
    String currenturl = (String) i.next();


     if ((currenturl.length() > 0 && currenturl
     .startsWith("http://www.skyscape.com"))) {

     if (!currenturl.startsWith("http://www.skyscape.com/estore/")&&
     (!currenturl.startsWith("http://www.skyscape.com/demos/"))) {
     System.out.println(currenturl);

     getResponseCode(currenturl);
     }
     }
     }


    writetoexcel();
}

public void setFinalLinkSet(Set<String> finalLinkSet) {
    this.finalLinkSet = finalLinkSet;
}

// function to get link from page and return array list of links
public Set<String> getLinksOnPage(String url) {

    ArrayList<WebElement> secondaryUrl = new ArrayList<WebElement>();
    secondaryUrl = (ArrayList<WebElement>) w.findElements(By.tagName("a"));

    for (int i = 0; i < secondaryUrl.size(); i++) {

        secondaryset.add((secondaryUrl.get(i).getAttribute("href")
                .toString()));
    }

    return secondaryset;
}

// function to fetch link from array list and store unique links in hashset
public Set<String> getUniqueList(ArrayList<WebElement> url_list) {

    for (int i = 0; i < url_list.size(); i++) {
        uniqueLinkSet.add(url_list.get(i).getAttribute("href").toString());
    }

    return uniqueLinkSet;
}

public boolean getResponseCode(String url) {
    boolean isValid = false;

    if (result == null) {
        result = new HashMap<String, String>();
    }

    try {
        URL u = new URL(url);
        w.navigate().to(url);
        HttpURLConnection h = (HttpURLConnection) u.openConnection();
        h.setRequestMethod("GET");
        h.connect();
        System.out.println(h.getResponseCode());

        if ((h.getResponseCode() != 500) && (h.getResponseCode() != 404)
                && (h.getResponseCode() != 403)
                && (h.getResponseCode() != 402)
                && (h.getResponseCode() != 400)
                && (h.getResponseCode() != 401)) {
            // && (h.getResponseCode() != 302)) {

            //getLinksOnPage(url);

            Set<String> unique2 = getLinksOnPage(url);
            setFinalLinkSet(unique2);

            result.put(url.toString(), "" + h.getResponseCode());

        } else {

            result.put(url.toString(), "" + h.getResponseCode());

            FC++;
        }

        return isValid;
    } catch (Exception e) {

    }
    return isValid;
}

private void writetoexcel() throws IOException, RowsExceededException,
        WriteException {

    FileOutputStream fo = new FileOutputStream("OldLinks.xls");
    WritableWorkbook wwb = Workbook.createWorkbook(fo);
    WritableSheet ws = wwb.createSheet("Links", 0);
    int recordsToPrint = result.size();

    Label HeaderUrl = new Label(0, 0, "Urls");
    ws.addCell(HeaderUrl);
    Label HeaderCode = new Label(1, 0, "Response Code");
    ws.addCell(HeaderCode);
    Label HeaderStatus = new Label(2, 0, "Status");
    ws.addCell(HeaderStatus);
    Iterator<Entry<String, String>> it = result.entrySet().iterator();
    while (it.hasNext() && count < recordsToPrint) {
        String Responsecode = null;
        Map.Entry<String, String> pairs = it.next();
        System.out.println("Value is --" + pairs.getKey() + "  -  "
                + pairs.getValue() + "\n");

        Label Urllink = new Label(0, count, pairs.getKey());

        Label RespCode = new Label(1, count, pairs.getValue());

        Responsecode = pairs.getValue();
        System.out.println(Responsecode);
        if ((Responsecode.equals("500")) || (Responsecode.equals("404"))
                || (Responsecode.equals("403"))
                || (Responsecode.equals("400"))
                || (Responsecode.equals("402"))
                || (Responsecode.equals("401"))) {
            // || (Responsecode.equals("302"))) {
            Label Status1 = new Label(2, count, "Fail");
            ws.addCell(Status1);
        } else {
            Label Status2 = new Label(2, count, "Pass");
            ws.addCell(Status2);
        }

        try {
            ws.addCell(Urllink);
        } catch (RowsExceededException e) {
            e.printStackTrace();
        } catch (WriteException e) {

            e.printStackTrace();
        }
        ws.addCell(RespCode);
        count++;
    }

    Label FCS = new Label(4, 1, "Fail Urls Count is = " + FC);
    ws.addCell(FCS);
    wwb.write();
    wwb.close();

}

}

2 个答案:

答案 0 :(得分:0)

简而言之,就我理解的问题而言:你有(至少)两个线程(尽管我在太长的代码示例中找不到它们),一个是向HashSet添加条目,并且其他应该在将元素添加到HashSet时连续列出元素。 第1步:您应该为此使用并发数据结构,但不是简单的HashSet。 第二:HashSet的迭代器不支持并发修改,因此你现在可以拥有一个迭代器&#34; waiting&#34;添加新条目。

最好是将代码更改为使用某种事件消息模式(有时也称为广播/侦听器),其中查找新URL会生成事件,代码的其他部分会侦听然后编写它们到文件。

答案 1 :(得分:0)

您的循环结束(早于期望),原因如下:

  • for循环

    的初始部分Iterator<String> i = finalLinkSet.iterator()
    for(Iterator<String> i = finalLinkSet.iterator(); i.hasNext(); ) {
    
    启动循环时,

    评估一次。因此,即使在某些地方,也不会对finalLinkSet的更改做出反应。

  • 您未对finalLinkSet进行任何更改。而是在调用

    时用新的集合覆盖它
    setFinalLinkSet(unique2);
    

所以你应该:

  • 使用列表,因此您已订购了元素。 (向无序集添加条目将使您无法知道已经迭代过的那些)。因此,我建议您使用ArrayList<String>,因此您可以通过性能的小缺点获得持续访问时间,以便在添加新条目时调整大小。
  • 修改你的for循环以使用索引,所以一次评估init-part就足够了,你可以对列表大小的变化做出反应:

    for(int i = 0; i < finalLinkList.size(); i++) {
        System.out.println(finalLinkSet.size());
        String currenturl = (String) finalLinkList.get(i);
    
  • 然后,您应该:

    而不是覆盖列表
    // for both occurrences
    addToFinalLinkList(...); // see new code below
    

    public void addToFinalLinkList(Set<String> tempSet) {
        for(String url: tempSet)
        {
            if(!finalLinkList.contains(url))
                finalListList.add(url);  
        }
    }
    

    从性能的角度来看,我知道这不是最好的,但是因为你在测试中,所以这不应该是我所看到的问题......