【问题标题】:How to properly refresh a list while using it for iterating如何在使用列表进行迭代时正确刷新列表
【发布时间】:2015-08-19 13:47:39
【问题描述】:

我有以下问题。我正在从 SonicWall 中删除一些防火墙规则。我这样做的方法是从声波墙中获取所有规则,找到匹配的规则,将它们存储在一个列表中并使用这个列表来发出删除它们的命令。删除规则的方法是使用 SSH 和带有其 ID 的命令。我遇到的问题是,每次删除 ID 时,所有 ID 都会更改,导致第二个命令尝试删除不存在的访问规则(或者更糟糕的是错误的访问规则)。我为了克服这个问题,在每次删除过程之后,我都会刷新我订购的列表以获取更新的元素,从而获得它们的新 ID。我面临的问题是列表的更新不正确(它发生在 for each 循环中),因为列表被用作迭代器(导致发出错误的命令)。

用新元素更新此列表的最佳和最安全的方法是什么?

下面是有问题的代码部分:

multiResult = expect.expect(anyOf(regexp("(.*)" + promptPattern)));     
        accessRules = getAccessRules(multiResult, accessRule);
        if(accessRules == null){
            Trc.trc("No access rules found to delete");
            return false;
        }

        numberOfRulesToDelete = accessRules.size();
        int size = numberOfRulesToDelete;
        IntList deleteRulesId = new IntList();

        while(numberOfRulesToDelete != 0){
            for(AccessRule arToDelete : accessRules){
            expect.sendLine("configure");
            multiResult = expect.expect(anyOf(regexp("(.*)" + confmodePromptPattern)));
            Result showCmdResult = multiResult.getResults().get(0);
            GenericCmdDto outPut = null;
            ObjectMapper objectMapper = new ObjectMapper();
            GenericFailedCmdDto failedOutPut = null;
            String swResponse = null;

            swResponse = handleSWConfModeResponse(showCmdResult);
            outPut = objectMapper.readValue(createSuccessfullJSONResponse(swResponse.getBytes()), GenericCmdDto.class);
            if(outPut.getSuccess()){//if change to configure command was successfull
                Result confCmdResult = null;
                Trc.trc("Configure command: " + outPut.getSuccess());
                expect.sendLine("no access-rule id "  + arToDelete.getIndex());
                MultiResult confResult = expect.expect(anyOf(regexp("(.*)" + confmodePromptPattern)));
                confCmdResult = confResult.getResults().get(0);

                swResponse = handleSWConfModeResponse(confCmdResult);
                outPut = objectMapper.readValue(createSuccessfullJSONResponse(swResponse.getBytes()), GenericCmdDto.class);
                if(outPut.getSuccess()){//if the delete command was successfull
                Trc.trc("Delete command issued successfully");
                expect.sendLine("commit");
                confCmdResult = expect.expect(anyOf(regexp("(.*)" + confmodePromptPattern)));

                swResponse = handleSWConfModeResponse(confCmdResult);
                outPut = objectMapper.readValue(createSuccessfullJSONResponse(swResponse.getBytes()), GenericCmdDto.class);
                if(outPut.getSuccess()){//if the commit command was successfull
                    Trc.trc("Commit command issued succesfully!");
                    Trc.trc("Deleted successfully access rule: " + arToDelete.getIndex());
                    deleteRulesId.addElement(arToDelete.getIndex());

                    expect.sendLine("exit");//change to no conf mode
                    confCmdResult = expect.expect(anyOf(regexp("(.*)" + promptPattern)));

                    swResponse = handleSWPromptModeResponse(confCmdResult);
                    outPut = objectMapper.readValue(createSuccessfullJSONResponse(swResponse.getBytes()), GenericCmdDto.class);
                    if(outPut.getSuccess()){//if the exit command was successfull
                    Trc.trc("Exit command issued successfully!");
                    operationSuccess = outPut.getSuccess();
                    }else{//if exit unsucessfull                
                    failedOutPut = objectMapper.readValue(createFailedJSONResponse(swResponse.getBytes()), GenericFailedCmdDto.class);
                    operationSuccess = outPut.getSuccess();
                    Trc.trc("Commit command has failed! Message: " + failedOutPut.getMessage() + ", Code: " + failedOutPut.getCode());
                    Trc.trc("Changing to show mode....");
                    expect.sendLine("exit");
                    multiResult = expect.expect(anyOf(regexp("(.*)" + promptPattern)));
                    showCmdResult = multiResult.getResults().get(0);

                    swResponse = handleSWPromptModeResponse(confCmdResult);

                    outPut = objectMapper.readValue(createSuccessfullJSONResponse(swResponse.getBytes()), GenericCmdDto.class);
                    if(outPut.getSuccess()){
                        Trc.trc("Exiting from conf mode..");
                        Trc.trc("Exit command: " + outPut.getSuccess());
                    }
                    return operationSuccess;
                    }
                }else{//if commit unsucessfull
                    failedOutPut = objectMapper.readValue(createFailedJSONResponse(swResponse.getBytes()), GenericFailedCmdDto.class);
                    operationSuccess = outPut.getSuccess();
                    Trc.trc("Commit command has failed! Message: " + failedOutPut.getMessage() + ", Code: " + failedOutPut.getCode());
                    Trc.trc("Changing to show mode....");
                    expect.sendLine("exit");
                    multiResult = expect.expect(anyOf(regexp("(.*)" + promptPattern)));
                    showCmdResult = multiResult.getResults().get(0);

                    swResponse = handleSWPromptModeResponse(showCmdResult);
                    outPut = objectMapper.readValue(createSuccessfullJSONResponse(swResponse.getBytes()), GenericCmdDto.class);
                    if(outPut.getSuccess()){
                    Trc.trc("Exiting from conf mode..");
                    Trc.trc("Exit command: " + outPut.getSuccess());
                    }
                    return operationSuccess;
                }
                }else{//if delete unsucessfull
                failedOutPut = objectMapper.readValue(createFailedJSONResponse(swResponse.getBytes()), GenericFailedCmdDto.class);
                operationSuccess = outPut.getSuccess();
                Trc.trc("Commit command has failed! Message: " + failedOutPut.getMessage() + ", Code: " + failedOutPut.getCode());
                Trc.trc("Changing to show mode....");
                expect.sendLine("exit");
                multiResult = expect.expect(anyOf(regexp("(.*)" + promptPattern)));
                showCmdResult = multiResult.getResults().get(0);

                swResponse = handleSWPromptModeResponse(showCmdResult);
                outPut = objectMapper.readValue(createSuccessfullJSONResponse(swResponse.getBytes()), GenericCmdDto.class);
                if(outPut.getSuccess()){
                    Trc.trc("Exiting from conf mode..");
                    Trc.trc("Exit command: " + outPut.getSuccess());
                }
                return operationSuccess;
                }

            }
            else{//if configure unsuccessfull
                failedOutPut = objectMapper.readValue(createFailedJSONResponse(swResponse.getBytes()), GenericFailedCmdDto.class);
                operationSuccess = outPut.getSuccess();
                Trc.trc("Commit command has failed! Message: " + failedOutPut.getMessage() + ", Code: " + failedOutPut.getCode());
                Trc.trc("Changing to show mode....");
                expect.sendLine("exit");
                multiResult = expect.expect(anyOf(regexp("(.*)" + promptPattern)));
                showCmdResult = multiResult.getResults().get(0);

                swResponse = handleSWPromptModeResponse(showCmdResult);
                outPut = objectMapper.readValue(createSuccessfullJSONResponse(swResponse.getBytes()), GenericCmdDto.class);
                if(outPut.getSuccess()){
                Trc.trc("Exiting from conf mode..");
                Trc.trc("Exit command: " + outPut.getSuccess());
                }
                return operationSuccess;
            }     
            expect.sendLine("show access-rules from " + accessRule.getFromZone() + " to " + accessRule.getToZone());
            multiResult = expect.expect(anyOf(regexp("(.*)" + promptPattern)));
            accessRules = getAccessRules(multiResult, accessRule);
            if(accessRules != null){
                numberOfRulesToDelete = accessRules.size();
            }else{
                Trc.trc("Deleting process complete!");
                numberOfRulesToDelete = 0;
                for(int i = 0; i < deleteRulesId.size(); i++){
                Trc.trc("Deleted " + size + " successfully rules: " + deleteRulesId.getElementAt(i));
                }
            }
            }  
        }
        return operationSuccess;

【问题讨论】:

  • 请去掉代码中不相关的部分并创建一个SSCCE来显示问题。
  • 我同意 Keppil 的观点,即代码似乎包含太多与问题无关的部分,但除此之外,您可以尝试直接使用迭代器(使用 hasNext() 和 next() 进行迭代)并调用remove() 在需要删除的元素的迭代器上。如果有可能在迭代器已经存在的地方插入新元素,这可能是一个问题,所以不要在迭代时添加新元素。 (如果只是 ids 改变并且顺序是不变的,那应该不是问题)。

标签: java json list


【解决方案1】:

您不应该在遍历列表时更新它。

改用副本。

【讨论】:

    【解决方案2】:

    对您使用列表的迭代器有帮助吗?您可以使用迭代器删除方法并立即从列表中删除该项目。

    【讨论】:

    • 我已经考虑过了,但这有什么帮助?我的意思是您第一次收到来自 SonicWall 的响应,该响应用于确定与它们一起初始化列表的元素数量。然后你使用第一个元素的 id 来删除它。然后刷新列表,默认情况下您的元素更少。我不明白为什么要从列表中删除它,因为刷新列表时它不会存在。
    • 最后我修改了有问题的方法,不包括循环,因为它不需要。但是很高兴看到一个关于如何做我所要求的事情的明确答案。
    猜你喜欢
    • 2023-03-23
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    相关资源
    最近更新 更多