zoukankan      html  css  js  c++  java
  • (一)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
    
  • 相关阅读:
    memcached源码剖析5:并发模型
    memcached源码剖析4:并发模型
    深入剖析php执行原理(4):函数的调用
    深入剖析php执行原理(2):函数的编译
    剖析php脚本的超时机制
    strerror的坑
    深入理解php中的ini配置(2)
    深入理解php中的ini配置(1)
    一个“日期”字符串进行比较的case
    用valgrind检测php扩展内存泄露
  • 原文地址:https://www.cnblogs.com/everyingo/p/12941845.html
Copyright © 2011-2022 走看看