【java】for-each 循环

详情参看 oracle 官方文档: The For-Each Loop

Iterator 类提供的迭代方法:代码丑陋,Iterator 实例出现了三次容易出现错误

    @Test
    public void iteratorTest() {
        List<String> names = this.createList();
        for (Iterator<String> i = names.iterator(); i.hasNext();) {
            LOGGER.debug("name is {}", i.next());
        }
    }

    private List<String> createList() {
        List<String> names = new ArrayList<>();
        names.add("小明");
        names.add("小强");
        names.add("小红");
        return names;
    }

for-each 循环:代码简洁,避免实例变量的重复出现,规避了代码风险;

    @Test
    public void forEachNewTest() {
        List<String> names = this.createList();
        for (String name:names) {
            LOGGER.debug("name is {}", name);
        }
    }
释义 :冒号可以看做是 " in.",上面的循环翻译过来就是  "for each String in names". for-each 循环 是和 泛型(generics)的完美结合,在保持类型安全的同时,移除了丑陋的代码:即不需要声明一个泛型,也不需要声明一个 Iterator 迭代器(编译器会自己处理)。

常见的 迭代器 Iterator  使用错误示例:

    @Test
    public void mistakeTest() {
        List<String> names = this.createList();
        List<String> fruits = this.createFruit();
        List<Person> source = new ArrayList<>();
        for (Iterator<String> i1 = names.iterator(); i1.hasNext();) {
            for (Iterator<String> i2 = fruits.iterator(); i2.hasNext();) {
                source.add(new Person(i1.next(), i2.next()));
            }
        }
    }

    private List<String> createList() {
        List<String> names = new ArrayList<>();
        names.add("小明");
        names.add("小强");
        names.add("小红");
        names.add("小张");
        return names;
    }

    private List<String> createFruit() {
        List<String> fruits = new ArrayList<>();
        fruits.add("apple");
        fruits.add("orange");
        return fruits;
    }

    private class Person {
        private String name;
        private String fruit;

        public Person() {
        }

        public Person(String name, String fruit) {
            this.name = name;
            this.fruit = fruit;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getFruit() {
            return fruit;
        }

        public void setFruit(String fruit) {
            this.fruit = fruit;
        }
    }

最后生成的 source list 集合中只有四条数据,并不是我们想要的结果,原因是 外部集合(name)对应的 迭代器 的 next 方法被调用了太多次,内部集合(fruits) 和 外部集合(names) 对应的 迭代器对象的 next 方法 在 内部循环中都被调用。修复这个错误的示例代码:source 的 list 集合中有 8 个 对象。

    @Test
    public void mistakeFixTest() {
        List<String> names = this.createList();
        List<String> fruits = this.createFruit();
        List<Person> source = new ArrayList<>();
        for (Iterator<String> i1 = names.iterator(); i1.hasNext();) {
            String name = i1.next();
            for (Iterator<String> i2 = fruits.iterator(); i2.hasNext();) {
                source.add(new Person(name, i2.next()));
            }
        }
    }

for-each 循环是为 嵌套循环 而定制的,不会产生以上的错误:

    @Test
    public void mistakeForEachTest() {
        List<String> names = this.createList();
        List<String> fruits = this.createFruit();
        List<Person> source = new ArrayList<>();
        for (String name:names) {
            for (String fruit:fruits) {
                source.add(new Person(name, fruit));
            }
        }
        LOGGER.debug("source size is {}", source.size());
    }

for-each 循环 同样适用于 数组 ,当循环数组时,隐藏的是 数组的位置索引,而集合隐藏的是 迭代器对象。

使用 for-each 的好处有很多,美化代码,避免错误,但也不是所有的地方都能用 for-each 循环,例如,如果你想循环集合,并根据条件删除 或者 替换 集合中符合条件的元素时,因为不能调用到 Iterator 实例来  删除或者 替换,所以这种情况下不能使用 for-each 循环。另外,对于 并行遍历多个集合 循环也是不可用的。

    @Test
    public void filterTest() {
        List<String> fruits = this.createFruit();
        for (Iterator<String> i = fruits.iterator(); i.hasNext();) {
            if (i.next().length() == 5) {
                i.remove();
            }
        }
        LOGGER.debug("fruits list size is {}", fruits.size());
    }

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页