1、 不要在 foreach 循环里进行元素的 remove/add 操作,可以在fori中进行remove/add。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。【参考:https://my.oschina.net/u/3955185/blog/4496726】
//正例一:
List list = new ArrayList<>();
list.add("1");
list.add("2");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
}
}
//正例二:
for (int i=0;i < list.size();i++) {
if (list.get(i)==2) {
list.remove(i);
}
}
//反例:
for (String item : list) {
if ("2".equals(item)) {
list.remove(item);
}
}
原因:由于foreach底层是用iterator进行遍历,源代码如下:
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
其中checkForComodification()具体实现为:
final void checkForComodification() {
if (modCount != expectedModCount){
throw new ConcurrentModificationException();
}
}
从源代码可以看出,当modCount != expectedModCount 会抛异常,使用list的remove()操作之后,modCount会加1,但是expectedModCount不会加1,即两值不等,会抛异常。 使用Iterator的remove()会更改expectedModCount的值,故需使用此方式进行remove/add。
public void remove() {
if (lastRet < 0){
throw new IllegalStateException();
}
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
如果使用fori进行remove/add,不会走checkForComodification()方法,所以也可以使用fori进行操作,如正例2。
2、Integer比较的时候,使用equals,否则当比较的数据不在-128-127之间,比较的不是值,而是对象的引用,比较结果不是预期值。
参考:《Java开发手册-嵩山版.pdf》