使用迭代器迭代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中删除的名称列表。
答案 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");
}