侧边栏壁纸
博主头像
phoenix-blog 博主等级

悄咪咪的,怕发现

  • 累计撰写 13 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Java中for和foreach使用区别

phoenix
2024-09-21 / 0 评论 / 0 点赞 / 25 阅读 / 0 字 / 正在检测是否收录...

在进行集合遍历操作删除或修改元素的时候会遇到一部分问题

遍历元素

// 遍历测试
@Test
void contextLoads() {
    String[] array = {"1", "2", "3"};
    for (String i : array) {
        System.out.println(i);
    }

    ArrayList<String> list = new ArrayList<>();
    list.add("111");
    list.add("222");
    list.add("333");
    for (String i : list) {
        System.out.println(i);
    }
}

1
2
3
111
222
333

再来看看编译后的源码(idea自带,在target包里打开类源码文件即可)

String[] array = new String[]{"1", "2", "3"};
String[] var2 = array;
int var3 = array.length;
for(int var4 = 0; var4 < var3; ++var4) {
    String i = var2[var4];
    System.out.println(i);
}

ArrayList<String> list = new ArrayList();
list.add("111");
list.add("222");
list.add("333");
Iterator var7 = list.iterator();
while(var7.hasNext()) {
    String i = (String)var7.next();
    System.out.println(i);
}

可见,遍历数组使用的是原始for循环,集合的话使用的是Iterator迭代器。

删除元素

ArrayList<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
System.out.println(list);

使用for循环

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


[111, 222, 333]
[111, 333]

使用foreach

for (String i : list) {
    list.remove("222");
}
 System.out.println(list);

java.util.ConcurrentModificationException
  at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095)
  at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1049)
  at com.demo.base.demo23.Demo23ApplicationTests.deleteTest(Demo23ApplicationTests.java:41)
  at java.base/java.lang.reflect.Method.invoke(Method.java:580)
  at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
  at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

原因

迭代器内部的每次遍历都会记录List内部的modcount当做预期值,然后在每次循环中用预期值与List的成员变量modCount作比较,但是普通list.remove调用的是List的remove,这时modcount++,但是iterator内记录的预期值并没有变化,所以会报错。

如果想要删除元素的话需要使用迭代器内部的remove方法

Iterator<String> it = list.iterator();
while (it.hasNext()){
    String next = it.next();
    // if外使用list的remove方法还是会报错的
    if(next.equals("222")){
        it.remove();// 这里使用的是迭代器里面的remove()方法,
        // 当然如果使用list的remove方法在此删除质地感元素的话是成功的,比如:list.remove("222")
    }
}
System.out.println(list);

[111, 222, 333]
[111, 333]

上面的写法可以简化成lambda表达式

list.removeIf(next -> next.equals("222"));

修改元素

使用原始for

// 修改测试
@Test
void updateTest() {
    ArrayList<String> list = new ArrayList<>();
    list.add("111");
    list.add("222");
    list.add("333");
    System.out.println(list);
    for (int i = 0; i <list.size(); i++) {
        list.set(i,"444");
    }
    System.out.println(list);
}

[111, 222, 333]
[444, 444, 444]

可以修改元素

使用foreach

// 修改测试
@Test
void updateTest() {
    ArrayList<String> list = new ArrayList<>();
    list.add("111");
    list.add("222");
    list.add("333");
    System.out.println(list);
//        for (int i = 0; i <list.size(); i++) {
//            list.set(i,"444");
//        }

    for (String i : list) {
        i="444";
    }
    System.out.println(list);
}


[111, 222, 333]
[111, 222, 333]

修改元素不行,修改元素的属性可不可以呢?

foreach修改元素属性

创建一个学生类

@Data
@AllArgsConstructor
@NoArgsConstructor
class Student {
    private int age;
    private String name;
}

接下来测试代码

@Test
void updateByElementTest() {
    Student student=new Student(1,"huge");
    Student student1=new Student(1,"xiaoyao");
    List<Student> studentList=new ArrayList<>();
    studentList.add(student);
    studentList.add(student1);
    System.out.println(student.getName());
    System.out.println(student1.getName());
    for(Student stu:studentList)
    {
        stu.setName("jingtian");
    }
    System.out.println(student.getName());
    System.out.println(student1.getName());
}

huge
xiaoyao
jingtian
jingtian

修改不了对象,却可以修改对象的属性。

总结

  1. for与foreach都可以遍历数组/集合,不过for则在较复杂的循环中效率更高。
  2. foreach不可以删除/修改集合元素,而for可以
  3. foreach和for都可以修改元素里面的属性

所以相比较下来for循环更为灵活。

0

评论区