Collection和Iterator接口

Posted everyingo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Collection和Iterator接口相关的知识,希望对你有一定的参考价值。

Collection接口是List,Set,Queue接口的父接口,该接口里定义的方法既可用于操作Set集合,也可用于操作List和Queue集合。

1.使用Lambda表达式遍历集合

Java8为Iterable接口新增了一个forEach(Consumer action)默认方法,该方法所需参数的类型是一个函数式接口,而Iterable接口是Collection接口的父接口,因此Collection结合也可以直接调用该方法。
当程序调用Iterable的forEach(Consumer action)遍历集合元素时,程序会依次将集合元素传给Consumer的accept(T t)方法,因为Consumer时函数式接口,因此可以使用Lambda表达式来遍历集合元素。

示例代码:

    public static void listForEach() {

        List<String> list = Arrays.asList(new String[]{"a", "b", "c", "d", "e", "f"});

        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("str:" + s);
            }
        });
    }

    public static void listForEachLambda() {

        List<String> list = Arrays.asList(new String[]{"a", "b", "c", "d", "e", "f"});

        list.forEach(s -> {
            System.out.println("lambda_str:" + s);
        });
    }

运行结果:

str:a
str:b
str:c
str:d
str:e
str:f
lambda_str:a
lambda_str:b
lambda_str:c
lambda_str:d
lambda_str:e
lambda_str:f

Iterable接口forEach(Consumer<? super T> action)源码:集合内部foreach调用Consumer对象(匿名对象)的accept()方法。

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

2.使用Java8增强的Iterator遍历集合元素

Iterator接口也是Java集合框架的成员,但是与Collection系系列,Map系列集合不一样:Collection系列集合,Map系列集合主要用于盛装其他对象,而Iterator则主要用于遍历Collection集合中的元素,Iterator对象也被称为迭代器。
iterator 遍历代码:

        List<String> list = new ArrayList<>(Arrays.asList(new String[]{"a", "b", "c", "d", "e", "f"}));
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            String str = (String) iterator.next();
            if ("c".equals(str)) {
                //从集合中删除上一次next()方法返回的元素
                iterator.remove();
            }
        }
        //使用Lambda表达式遍历Iterator
        list.iterator().forEachRemaining(s -> System.out.println(s));

运行结果:

a
b
d
e
f

remove代码:

        List<String> list = new ArrayList<>(Arrays.asList(new String[]{"a", "b", "c", "d", "e", "f"}));
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            String str = (String) iterator.next();
            if ("c".equals(str)) {
                //使用Iterator迭代过程中,不可修改集合元素,将引发异常:java.util.ConcurrentModificationException
                list.remove(str);
            }
            System.out.println(str);
        }
        List<String> list = new ArrayList<>(Arrays.asList(new String[]{"a", "b", "c", "d", "e", "f"}));
        for (String s : list) {
            if ("c".equals(s)) {
                // 将引发异常:java.util.ConcurrentModificationException
                list.remove(s);
            }
        }

3.使用Java8新增的Predicate操作集合

Java8为Collection集合新增了一个removeIf(Predicate filter)方法,该方法将会批量删除符合filter条件的所有元素。该方法需要一个Predicate(谓词)对象作为参数,Predicate也是函数式接口,因此也可以使用Lambda表达式作为参数。

示例代码:

    public static void listPredicate() {
        /**
         * 调用Arrays.asList()生产的List的add、remove方法时报异常,这是由Arrays.asList() 返回的市Arrays的内部类ArrayList, 而不是java.util.ArrayList。
         * Arrays的内部类ArrayList和java.util.ArrayList都是继承AbstractList,remove、add等方法AbstractList中是默认throw UnsupportedOperationException而且不作任何操作。
         * java.util.ArrayList重新了这些方法而Arrays的内部类ArrayList没有重新,所以会抛出异常
         */
        List<String> aslist = Arrays.asList(new String[]{"1", "2", "3", "4", "5", "6"});

        /**
         * 解决方法如下
         */
        List<String> list = new ArrayList<>(aslist);
        list.removeIf(new Predicate<String>() {

            @Override
            public boolean test(String s) {
                if (s.equals("3")) {
                    return true;
                }
                return false;
            }
        });

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

    }
    public static void listPredicateLambda() {

        List<String> aslist = Arrays.asList(new String[]{"1", "2", "3", "4", "5", "6"});

        List<String> list = new ArrayList<>(aslist);

        list.removeIf(s -> (s.equals("3")));

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


    }

运行结果:

1
2
4
5
6

Collection接口removeIf(Predicate<? super E> filter)源码:遍历集合内部元素依据Predicate对象(匿名对象)test()自定义方法体返回值决定是否删除集合中的对象。

    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

PredicateDemo:

    public static void listPredicateDemo() {
        List<String> aslist = Arrays.asList(new String[]{"1", "2", "2", "2", "3", "3"});
        System.out.println("1出现的次数:" + totalNumer(aslist, (s -> (s.equals("1")))));
        System.out.println("2出现的次数:" + totalNumer(aslist, (s -> (s.equals("2")))));
        System.out.println("总数字:" + totalNumer(aslist, (s -> (1 == 1))));

    }

    private static int totalNumer(Collection collection, Predicate predicate) {
        int total = 0;
        for (Object o : collection) {
            if (predicate.test(o)) {
                total++;
            }
        }
        return total;
    }

运行结果:

1出现的次数:1
2出现的次数:3
总数字:6

以上是关于Collection和Iterator接口的主要内容,如果未能解决你的问题,请参考以下文章

Java集合框架--Collection接口的使用 & 迭代器(Iterator)遍历原理

Collection接口与Iterator接口

java collection和Iterator

Java容器Collection与迭代器Iterator

Collection接口 Collection的通用方法 foreach Iterator 迭代器

Iterable与Collection源码学习