在迭代器中从ArrayList中删除多个项目

时间:2018-02-14 09:24:41

标签: java arraylist iterator java-7

使用迭代器迭代ArrayList时,从ArrayList中删除多个项是否安全?

Iterator<String> iterator = nameList.iterator();
 while(iterator.hasNext()){
     String s = iterator.next();
     List<String> list = work(s);
     for (String s1 : list) {
        nameList.remove(s1);   
    }
}

在while循环的运行时期间,work()方法返回一个应该从nameList中删除的名称列表。

3 个答案:

答案 0 :(得分:10)

不,它不安全,可以抛出ConcurrentModificationException。您可以在临时List中收集要删除的所有元素,然后在while循环后调用list.removeAll(tmpList)以执行删除。

Iterator<String> iterator = nameList.iterator();
List<String> removed = new ArrayList<>();
while(iterator.hasNext()){
    String s = iterator.next();
    removed.addAll(work(s));
}
list.removeAll(removed);

我意识到这可能效率较低,因为您可能会在work(s)上调用String本应从早先List删除的tempList。这可以通过将Set更改为work(s)来改进,而仅String中的Set调用Iterator<String> iterator = nameList.iterator(); Set<String> removed = new HashSet<>(); while(iterator.hasNext()){ String s = iterator.next(); if (!removed.contains(s)) { removed.addAll(work(s)); } } list.removeAll(removed); 不在grammar SASDTModel; parse : block+ EOF; block : if_block+ # oneOrMoreIfBlock | assignment_block+ # assignmentBlocks ; if_block : if_statement (else_if_statement)* else_statement? ; /*nested_if_else_statement : If if_condition Then Do? ';'? if_statement (else_if_statement)* else_statement? End? ';'? ;*/ if_statement : If '('? if_condition ')'? Then if_block # nestedIfStatement | If '('? if_condition ')'? Then expression Equal expression ';' # ifStatement | If expression In '(' expression_list+ ')' Then expression Equal expression ';' # ifInBlock ; else_if_statement : Else If '('? if_condition ')'? Then expression Equal expression ';' # elseIf | Else If expression In '(' expression_list+ ')' Then expression Equal expression ';' # elseIfInBlock ; if_condition : Identifier (Equal|ComparisionOperators) Quote? expression+ Quote? # equalCondition | expression # expressionCondition | expression equals_to_null # checkIfNull | expression op=(And|Or) expression # andOrExpression ; /*if_range_condition : expression ComparisionOperators expression ComparisionOperators expression ;*/ else_statement : Else expression Equal expression ';' ; assignment_block : Identifier Equal Identifier '(' function_parameter ')' ';' # functionCall | Identifier Equal expression expression* ';' # assignValue ; expression : Value # value | Identifier # identifier | SignedFloat # signedFloat | '(' expression ')' # expressionBracket | expression '(' expression_list? ')' # expressionBracketList | Not expression # notExpression | expression (Min|Max) expression # minMaxExpression | expression op=('*'|'/') expression # mulDivideExpression | expression op=('+'|'-') expression # addSubtractExpression | expression ('||' | '!!' ) expression # orOperatorExpression | expression ComparisionOperators expression ComparisionOperators expression # inRangeExpression | expression ComparisionOperators Quote? expression+ Quote? # ifPlainCondition | expression (Equal|ComparisionOperators) Quote {_input.get(_input.index() -1).getType() == WS}? Quote # ifSpaceStringCondition | expression Equal expression # equalExpression ; expression_list : Quote? expression+ Quote? Comma? # generalExpressionList | Quote ({_input.get(_input.index() -1).getType() == WS}?)? Quote Comma? # spaceString ; function_parameter : expression+ ; equals_to_null : Equal Pt ; /*ArithmeticOperators : '+' | '-' | '*' | '/' | '**' ;*/ Equal : '=' ; ComparisionOperators : '<' | '>' | '<=' | '>=' ; And : '&' | 'and'; Or : '|' | '!' ; Not : '^' | '~' ; Min : '><'; Max : '<>'; If : 'IF' | 'if' | 'If' ; Else : 'ELSE' | 'else' | 'Else'; Then : 'THEN' | 'then' | 'Then' ; In : 'IN' | 'in'; Do : 'do' | 'Do'; End : 'end' | 'END'; Value : Int | DOUBLE | '-'DOUBLE | '-'Int | SignedFloat | 'null'; Int : [0-9]+; SignedFloat : UnaryOperator? UnsignedFloat ; MUL : '*' ; // assigns token name to '*' used above in grammar DIV : '/' ; ADD : '+' ; SUB : '-' ; DOUBLE : Int Pt Int | Pt Int | Int ; Pt : '.'; UnaryOperator : '+' | '-' ; UnsignedFloat : ('0'..'9')+ '.' ('0'..'9')* Exponent? | '.' ('0'..'9')+ Exponent? | ('0'..'9')+ Exponent ; Exponent : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; Comma : ','; Quote : '\'' | '"' ; Identifier : [a-zA-Z_] [a-zA-Z_0-9]* ; WS : ( ' ' | '\t' | '\r' | '\n' )-> channel(HIDDEN);

{{1}}

答案 1 :(得分:2)

如果使用故障安全的ListIterator,则可以实现逻辑。以下是一个基本示例:

Set<String> removed = new HashSet<>();
    ArrayList<String> nameList = new ArrayList<String>();

            ListIterator<String> iterator = nameList.listIterator();
             while(iterator.hasNext()){
                 String s = iterator.next();
                 if (!removed.contains(s)) {
        removed.addAll(work(s));
    }

            }


 nameList.removeAll(removed);
                 System.out.println(nameList);

根据您的逻辑,您必须考虑性能。如果性能不是一个因素,您可以继续通过ListIterator从列表中添加/删除。

答案 2 :(得分:0)

如前所述,从迭代列表中删除项目并不安全。这是抛出ConcurrentModificationException的代码:

List<String> list = new ArrayList<>(Arrays.asList("1", "2", "3"));
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String s = iterator.next();
    list.remove("1");
}