阿里巴巴为什么这样强制从List中删除元素
你从下面List中删除一颗星。
ListtempList = Arrays.asList("水星","金星","地球","火星", "木星","土星","天王星","海王星","冥王星","冥王星");
怎么删除List中的冥王星呢?[PS为了演示某些删除方法不可靠,重复写了冥王星] 。
先写一段阿里规约:
【强制】不要再foreach循环里进行元素的remove/add操作,remove元素请使用Iterator方式,如果并发的操作,需要对Iterator对象加锁。
好了,那就让我们来写所有可能删除元素的方法
1:普通的for循环的删除(不可靠)。
Listlist = new ArrayList(tempList); for (int i = 0; i ) { String str = list.get(i); if ("冥王星".equals(str)) { list.remove(i); } } System.out.println(list);
运行结果如下:
[水星, 金星, 地球, 火星, 木星, 土星, 天王星, 海王星, 冥王星]
奇了怪了,没删除干净?
问题出在 list.size(),因为 list.size() 和 i 都是动态变化的,i 的值一直在累加,list.size() 一直在减少,所以 list 就会早早结束了循环。所以这种方式虽然不会报错,但存在隐患,并且不容易被察觉,不建议使用。
2:普通的for循环提取变量进行删除(这个更不可靠,会报错)。
Listlist = new ArrayList(tempList); int size = list.size(); for (int i = 0; i ) { String result = list.get(i); if ("冥王星".equals(result)) { list.remove(i); } } System.out.println(list);
结果如下:
这更不对了,一下子搞出个下标越界。
因为 size 变量是固定的,但 list 的实际大小是不断减小的,而 i 的大小是不断累加的,一旦 i >= list 的实际大小肯定就异常了。
3:普通的for循环倒叙删除(这个用法可以,但也不推荐,倒叙看着很别扭,个人意见)。
for (int i = list.size() - 1; i > 0; i--) { String result = list.get(i); if ("冥王星".equals(result)) { list.remove(i); } } System.out.println(list);
运行结果如下:
[水星, 金星, 地球, 火星, 木星, 土星, 天王星, 海王星]
4:使用增强的for循环删除(会抛出异常,不推荐,注意我这次为了演示效果,把行星的顺序换一下),不少开发者喜欢用这种方式。
ListtempList = Arrays.asList("水星","金星","地球","火星", "冥王星","土星","天王星","海王星","冥王星","木星"); List list = new ArrayList(tempList); for (String item : list) { if ("冥王星".equals(item)) { list.remove(item); } } System.out.println(list);
结果如下:
奇了怪了,又抛异常了。不过这次的异常和上面的下标异常不太一样,这次是:
java.util.ConcurrentModificationException
这个是集合操作中很常见的异常之一,即并发修改异常!
增强的 for循环,其内部是调用的 Iterator 的方法,取下个元素的时候都会去判断要修改的数量(modCount)和期待修改的数量(expectedModCount)是否一致,不一致则会报错,而 ArrayList 中的 remove 方法并没有同步期待修改的数量(expectedModCount)值,所以会抛异常了。
5、迭代器循环迭代器删除(可靠,也是十分推荐的用法)。
Iteratoriterator = list.iterator(); while (iterator.hasNext()){ String item = iterator.next() ; if ("冥王星".equals(item)){ iterator.remove(); } } System.out.println(list);
结果如下,十分完美和正确:
[水星, 金星, 地球, 火星, 土星, 天王星, 海王星, 木星]
这是因为迭代器中的 remove 方法将期待修改的数量(expectedModCount)值进行了同步。

6:迭代器循环集合删除(这个可能很多开发者也会这样写,也可能会抛出异常的)。
Iteratoriterator = list.iterator(); while (iterator.hasNext()){ String item = iterator.next() ; if ("冥王星".equals(item)){ list.remove(item); } } System.out.println(list);
结果如下:
7:Stream filter 过滤(十分推荐,当然使用这个删除需要JDK的环境在8及其8以上的版本)。
list = list.stream().filter(item -> !"冥王星".equals(item)).
collect(Collectors.toList());
System.out.println(list);
结果如下,十分完美和正确:
这个方法利用了 Stream 的筛选功能,快速过滤所需要的元素,虽然不是进行集合删除,但达到了同样的目的,这种方法要更简洁
看了上面的几个例子,相信你熟悉了List删除元素的用法了,希望你看了上面的例子,开发的时候不会再犯错了。
文章来源于互联网:阿里巴巴为什么这样强制从List中删除元素