Java集合——遍历集合元素并修改

摘要:本文主要总结了遍历集合的方式,以及在遍历时修改集合要注意的问题。

遍历Collection

对List和Set的遍历,有四种方式,下面以ArrayList为例进行说明。

1)普通for循环

代码如下:

 for (int i = 0; i < list.size(); i++) {
System.out.println(i);
}

如果要在普通for循环里对集合元素进行删除操作,可能会出现问题:

 public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(2);
list.add(4);
list.add(5);
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 2) {
list.remove(i);
}
}
System.out.println(list);
}

运行结果如下:

 [1, 2, 4, 5]

结果说明:

集合中有两个值为2的元素,但是在代码执行之后,值为2的元素并没有完全移除。

原因就在于当第一次判断 i = 1 位置上的值为2时,将这个元素删除,导致这个位置之后的所有元素都向前挪动一个位置,导致 i = 1 位置上的值变成了后面的2。

下次遍历时,判断 i = 2 位置上的值,也就是4,导致2被跳过去了,从而导致最后打印的结果和预期的不一致。

改进方法是在删除之后手动设置 i-- 即可。

2)增强for循环

代码如下:

 for (Integer i : list) {
System.out.println(i);
}

如果想在增强for循环里删除或者添加集合元素,那么一定会报异常:

 public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(2);
list.add(4);
list.add(5);
for (Integer i : list) {
if (i == 2) {
list.remove(i);
}
}
System.out.println(list);
}

运行结果如下:

 java.util.ConcurrentModificationException

结果说明:

因为增强for循环(foreach循环)本质上是隐式的iterator,由于在删除和添加的时候会导致modCount发生变化,但是没有重新设置expectedModCount,当你使用list.remove()后遍历执行iterator.next()时,方法检验modCount的值和的expectedModCount值,如果不相等,就会报ConcurrentModificationException。

3)使用迭代器

代码如下:

 Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}

如果在迭代的循化里使用list方法的add()方法和remove()方法,同样会报错:

 public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(2);
list.add(4);
list.add(5);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = (Integer) iterator.next();
if (i == 2) {
list.add(6);
}
}
}

运行结果如下:

 java.util.ConcurrentModificationException

如果在迭代器的循环里使用迭代器的remove()方法,则不会报错。

iterator()方法返回的Iterator类型的迭代器没有提供添加的方法,但是listIterator()方法返回的ListIterator类型的迭代器提供了add()方法和set()方法。

使用迭代器删除原数的代码如下:

 public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(2);
list.add(4);
list.add(5);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = (Integer) iterator.next();
if (i == 2) {
iterator.remove();
}
}
System.out.println(list);
}

运行结果如下:

 [1, 4, 5]

结果说明:

迭代器的remove()方法同时维护了modCount和expectedModCount,所以使用remove()方法可以达到预期的效果。

4)使用forEach方法

forEach()方法是JDK1.8新增的方法,需要配合Lambda表达式使用,代码如下:

 list.forEach(String -> System.out.println(String));

运行结果如下:

 1
2
3
4

遍历Map

对Map的遍历,有四种方式,下面以HashMap为例进行说明。

1)通过keySet()方法遍历key和value

通过keySet()方法获取到map的所有key值,遍历key值的集合,获取对应的value值。代码如下:

 for (Integer i : map.keySet()) {
System.out.println(i + " >>> " + map.get(i));
}

运行结果如下:

 0 >>> 000
1 >>> 111
2 >>> 222
3 >>> 333
4 >>> 444

在遍历的时候是可以修改的,但是不能添加和删除,否则会ConcurrentModificationException异常,代码如下:

 for (Integer i : map.keySet()) {
System.out.println(i + " >>> " + map.get(i));
if (map.get(i) == "222") {
map.put(i, "999");
}
}

运行结果如下:

 key= 0 and value= 000
key= 1 and value= 111
key= 2 and value= 999
key= 3 and value= 333
key= 4 and value= 444

2)通过entrySet()方法遍历key和value

这种方式同样支持修改,但不支持添加和删除,这种方式的效率最高,推荐使用,代码如下:

 for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " >>> " + entry.getValue());
}

3)通过entrySet()方法获取迭代器遍历key和value

这种方式同样支持修改,但不支持添加和删除,代码如下:

 Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, String> entry = iterator.next();
System.out.println(entry.getKey() + " >>> " + entry.getValue());
}

4)通过values()方法遍历所有的value

这种方式只能遍历value,不能遍历key,代码如下:

 for (String value : map.values()) {
System.out.println(value);
}

Java集合——遍历集合元素并修改的更多相关文章

  1. - 集合 遍历 foreach Iterator 并发修改 ConcurrentModificationException MD

    目录 目录 为什么不能在 foreach 循环里进行元素的 remove/add 操作 背景 foreach 循环 问题重现 fail-fast remove/add 做了什么 正确姿势 直接使用普通 ...

  2. java中遍历集合的三种方式

    第一种遍历集合的方式:将集合变为数组 package com.lw.List; import java.util.ArrayList; import java.util.List; import ja ...

  3. Java中遍历集合的常用方法

    一.List 1.普通for循环 for (int i = 0; i < list.size(); i++)){ String temp = (String)list.get(i); Syste ...

  4. java集合遍历删除指定元素异常分析总结

    在使用集合的过程中,我们经常会有遍历集合元素,删除指定的元素的需求,而对于这种需求我们往往使用会犯些小错误,导致程序抛异常或者与预期结果不对,本人很早之前就遇到过这个坑,当时没注意总结,结果前段时间又 ...

  5. iOS学习16之OC集合遍历和数组排序

    1.集合遍历 1> 遍历 集合(Collection):OC中提供的容器类:数组,字典,集合. 遍历:对集合中元素依次取出的过称叫做遍历. 三种方式:① for循环遍历: ② NSEnumera ...

  6. Java修炼——ArrayList常用的方法以及三种方式遍历集合元素。

    List接口ArrayList用法详解 ArrayList常用方法: 1. List.add():添加的方法(可以添加字符串,常量,以及对象) List list=new ArrayList(); l ...

  7. java list集合遍历时删除元素

    转: java list集合遍历时删除元素 大家可能都遇到过,在vector或arraylist的迭代遍历过程中同时进行修改,会抛出异常java.util.ConcurrentModification ...

  8. Java使用foreach遍历集合元素

    Java使用foreach遍历集合元素 1.实例源码 /** * @Title:ForEach.java * @Package:com.you.model * @Description:使用forea ...

  9. 黑马基础阶段测试题:创建一个存储字符串的集合list,向list中添加以下字符串:”C++”、”Java”、” Python”、”大数据与云计算”。遍历集合,将长度小于5的字符串从集合中删除,删除成功后,打印集合中的所有元素

    package com.swift; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; ...

随机推荐

  1. mysql 特定查询条件下导致的大海捞针

    order表: order type  gmt_create type 取值: 0,1  其中0非常多,1非常少. 当查询条件里 select * from order where type=0 an ...

  2. 监控linux各主机系统时间是否一致

    #!/bin/bashSTATE_OK=0 STATE_WARNING=1 STATE_CRITICAL=2 STATE_UNKNOWN=3PASSWD='**************'print_h ...

  3. Spring框架针对dao层的jdbcTemplate操作crud之delete删除数据库操作 Spring相关Jar包下载

    首先,找齐Spring框架中IoC功能.aop功能.JdbcTemplate功能所需的jar包,当前13个Jar包 1.Spring压缩包中的四个核心JAR包,实现IoC控制反转的根据xml配置文件或 ...

  4. 学习笔记(_huaji_)

    假如我没有见过太阳,我也许会忍受黑暗. 如果我知道自己会在哪里死去,我就永远都不去那儿.失败的经历,其实也有它的价值. 人的过失会带来错误,但要制造真正的灾难还得用计算机. 嘴角微微上扬已不复当年轻狂 ...

  5. POJ-3669-流星雨

    这题的话,卡了有两个小时左右,首先更新地图的时候越界了,我们进行更新的时候,要判断一下是不是小于零了,越界就会Runtime Error. 然后bfs 的时候,我没有允许它搜出300以外的范围,然后就 ...

  6. PHP 线上项目 无法操作

    部署到线上的项目,http 环境没有问题,首页展示没有问题,但是跳转页面展示到了本地, 解决办法 : 更改文件夹所属用户 chown -R apache:apache html

  7. springboot的启动类不能直接放在src/java目录下,不然会报错

    jar包的application.yml 会被项目的覆盖,导致找不到原有的配置

  8. EFCore CodeFirst模型迁移生成数据库备注(mysql)

    重写Mysql下sql脚本生成器 using Framework.NetCore.Extensions; using Framework.NetCore.Models; using Microsoft ...

  9. pytorch中torch.unsqueeze()函数与np.expand_dims()

    numpy.expand_dims(a, axis) Expand the shape of an array. Insert a new axis that will appear at the a ...

  10. [uiautomator篇]uiwatcher 的使用场景

    http://www.yangyanxing.com/article/use-watcher-in-uiautomator.html   今天在uiautomator中实践了watcher的用法,这个 ...