• Java—Java 8 新增特性详解(Predicate和Stream)


    Predicate接口

    Predicate接口介绍

      Predicate是函数式接口,可以使用Lambda表达式作为参数。Java 8为集合Collection新增了removeIf(Predicate filter)方法,可以批量删除符合filter条件的所有元素。

    Predicate接口使用范例

    测试Collection的removeIf()方法。
    示例1
    1)运行类:

    public class DemoApplication {
    
        public static void main(String[] args) {
    
            // 创建集合
            Collection collection = new HashSet();
    
            // 添加元素
            collection.add("book01");
            collection.add("book02");
            collection.add("book03");
            collection.add("b05");
            collection.add("b06");
    
            Collection collectionNew = new HashSet();
            // 使用Lambda表达式遍历传入新的集合
            collection.forEach(str -> collectionNew.add(str));
            System.out.println("collectionNew: " + collectionNew);
    
            // 使用Lambda表达式进行过滤(目标类型是Predicate)
            collection.removeIf(filter -> ((String)filter).length() < 5);
    
            // 使用Lambda表达式遍历打印
            collection.forEach(str -> System.out.println(str));
    
            
            }
    }
    

    2)运行结果:

    collectionNew: [book02, book01, b05, book03, b06]
    book02
    book01
    book03
    

      从上述结果中,我们可以看到调用Collection集合的removeIf()方法,可以批量过滤符合条件长度小于5的集合元素,程序是传入一个Lambda表达式进行过滤:collection.removeIf(filter -> ((String)filter).length() < 5);

    示例2
    使用Predicate接口的boolean test(T t);方法
    1)创建工具类:

    import java.util.Collection;
    import java.util.function.Predicate;
    
    /**
     * @author andya
     * @create 2020-03-24 14:08
     */
    public class PredicateUtil {
        public static int countCollectionElement(Collection collection, Predicate predicate){
            int total = 0;
            for (Object object : collection) {
                //通过Predicate的test()方法判断对象是否满足过滤条件
                if (predicate.test(object)) {
                    total ++;
                }
            }
    
            return total;
        }
    }
    

    2)运行类:

    public class DemoApplication {
    
        public static void main(String[] args) {
    
            // 创建集合
            Collection collection = new HashSet();
    
            // 添加元素
            collection.add("book_java编程思想");
            collection.add("book_c++核心技术");
            collection.add("book_java核心技术");
            collection.add("book_计算机网络");
            collection.add("book01");
            collection.add("book02");
    
            Collection collectionNew = new HashSet();
            // 使用Lambda表达式遍历传入新的集合
            collection.forEach(str -> collectionNew.add(str));
            System.out.println("collectionNew: " + collectionNew);
    
            System.out.println("包含java关键字的个数:" +
                    PredicateUtil.countCollectionElement(collection, ele -> ((String)ele).contains("java")));
            System.out.println("长度小于7的个数:" +
                    PredicateUtil.countCollectionElement(collection, ele -> ((String)ele).length() < 7));
            System.out.println("以book_为前缀的个数:" +
                    PredicateUtil.countCollectionElement(collection, ele -> ((String)ele).startsWith("book_")));
            }
    }
    

    3)运行结果:

    collectionNew: [book02, book01, book_java编程思想, book_java核心技术, book_计算机网络, book_c++核心技术]
    包含java关键字的个数:2
    长度小于7的个数:2
    以book_为前缀的个数:4
    

      定义了一个countCollectionElement()方法,使用Predicate动态传参,判断每个集合元素是否符合过滤条件。

    Stream流式接口

    Stream流式接口介绍

      Java 8新特性中还增加了流式处理,如Stream,IntStream,DoubleStream,LongStream等API。每个流式API还提供了对应的Builder,如Stream.Builder、IntStream.Builder、DoubleStream.Builder、LongStream.Builder。

    Stream使用步骤

    1. 通过Stream等API的builder()类方法去创建Stream对应的Builder类;
    2. 调用Builder的add()方法向流中添加多个元素;
    3. 调用Builder的build()方法获取对应的Stream;
    4. 调用Stream聚集方法;

    Stream使用示例

    public class DemoApplication {
    
        public static void main(String[] args) {
    
            //通过xxxStream的builder()方法去创建Builder
            IntStream intStream = IntStream.builder()
                    .add(1)
                    .add(-2)
                    .add(3)
                    .add(10)
                    .build();
    
            // 聚集方法(每次只能使用其中一条去执行,其他代码需注释,否则会报错)
            System.out.println("intStream的元素最大值是: " + intStream.max().getAsInt());
            System.out.println("intStream的元素最小值是: " + intStream.min().getAsInt());
            System.out.println("intStream的元素平均值是: " + intStream.average());
            System.out.println("intStream的元素总和是: " + intStream.sum());
            System.out.println("intStream的元素个数是: " + intStream.count());
            System.out.println("intStream是否包含任何元素平方大于10: "
                    + intStream.anyMatch(ele -> ele * ele > 10));
            System.out.println("intStream的所有元素立方是否大于10: "
                    + intStream.allMatch(ele -> ele * ele * ele > 10));
    
            // 每个元素都加1后映射成新的Stream
            IntStream intStreamNew = intStream.map(ele -> ele + 1);
            intStreamNew.forEach(ele -> System.out.println(ele));
            }
    }
    

    运行结果:将上述聚集方法所有执行结果放在一个里面进行展示,其实只能执行一条;

    intStream的元素最大值是: 10
    intStream的元素最小值是: -2
    intStream的元素平均值是: OptionalDouble[3.0]
    intStream的元素总和是: 12
    intStream的元素个数是: 4
    intStream是否包含任何元素平方大于10: true
    intStream的所有元素立方是否大于10: false
    2
    -1
    4
    11
    

    在上述示例中存在两种聚集方法:“中间方法”和“末端方法”。

    • 中间方法:中间操作允许流保持打开状态,并允许直接调用后续方法,如map()方法,返回值为另一个流;
    • 末端方法:末端方法是对流进行的最终操作,如sum()方法执行后,流就不可用,如果再用会报错Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed

    Stream的常用方法

    中间方法

    • filter(Predicate predicate):过滤Stream中不符合predicate过滤条件的元素。
    • mapToXxx(ToXxxFunction mapper):使用ToXxxFunction对流中的元素执行一对一的转换,方法返回的是新流中包含了ToXxxFunction转换生成的所有元素。
    • peek(Consumer action):依次操作每个元素,返回的流与原有流包含相同的元素,用于调试。
    • distinct():用于排序流中所有重复的元素,有状态的方法;
    • sorted():用于保证流中的元素在后续的访问中处于有序状态,也是有状态的方法。
    • limit(long maxSize):用于保证对该流的后续访问中最大允许访问的元素个数,是一个有状态的、短路方法。

    末端方法

    • forEach(Consumer action):遍历流中所有元素,执行action。
    • toArray():将流中所有元素转换成一个数组。
    • reduce():用于某个操作合并流中元素。
    • min():返回流中元素的最小值。
    • max():返回流中元素的最大值。
    • sum():返回流中元素的总和。
    • count():返回流中所有元素的数量。
    • anyMatch(Predicate predicate):判断流中是否至少包含一个元素符合predicate过滤条件。
    • allMatch(Predicate predicate):判断流中是否所有元素符合predicate过滤条件。
    • noneMatch(Predicate predicate):判断流中是否所有元素都不符合predicate过滤条件。
    • findFirst():返回流中的第一个元素。
    • findAny():返回流中的任意一个元素。

    Collection中的stream()方法

    public class DemoApplication {
    
        public static void main(String[] args) {
       		// 创建集合
            Collection collection = new HashSet();
    
            // 添加元素
            collection.add("book_java编程思想");
            collection.add("book_c++核心技术");
            collection.add("book_java核心技术");
            collection.add("book_计算机网络");
            collection.add("book01");
            collection.add("book02");
            collection.forEach(ele -> System.out.println(ele));
    
            System.out.println("-------------------------------------");
    
            System.out.println("包含java关键字的个数:"
                    + collection.stream().filter(ele -> ((String)ele).contains("java")).count());
            System.out.println("长度小于7的个数:"
                    + collection.stream().filter(ele -> ((String)ele).length() < 7).count());
            System.out.println("以book_为前缀的个数:"
                    + collection.stream().filter(ele -> ((String)ele).startsWith("book_")).count());
    
            System.out.println("-------------------------------------");
    
            //先调用Collection的stream()方法将集合转化为Stream;
            //再调用Stream的mapToInt()方法获取Stream对象的IntStream对象;
            //最后调用forEach()方法遍历IntStream中的元素。
            Collection collectionLength = new ArrayList();
            collection.stream().mapToInt(ele -> ((String)ele).length())
                    .forEach(ele -> ((ArrayList) collectionLength).add(ele));
            //等价于collectionLength.forEach(ele -> System.out.println(ele));
            collectionLength.forEach(System.out::println);
            }
    }
    

    运行结果

    book02
    book01
    book_java编程思想
    book_java核心技术
    book_计算机网络
    book_c++核心技术
    -------------------------------------
    包含java关键字的个数:2
    长度小于7的个数:2
    以book_为前缀的个数:4
    -------------------------------------
    6
    6
    13
    13
    10
    12
    

      通过collection.stream().filter(Predicate<? super T> predicate).count()这种方式就可以替换文章中前面创建的PredicateUtil的方法。
      除了直接使用Stream流式接口去处理Collection集合的元素,我们还可以通过Collection接口的stream()方法返回集合对应的流。
    步骤如下:

    1. 先调用Collection的stream()方法将集合转化为Stream;
    2. 再调用Stream的mapToInt()方法获取Stream对象的IntStream对象;
    3. 最后调用forEach()方法遍历IntStream中的元素。

    参考书籍《疯狂Java》

  • 相关阅读:
    javascript高级程序设计---Event对象三
    javascript高级程序设计---Event对象二
    javascript高级程序设计---Event对象
    javascript高级程序设计---CSS操作
    javascript高级程序设计---Element对象
    javascript高级程序设计---document节点
    javascript高级程序设计---NodeList和HTMLCollection
    javascript高级程序设计---DOM
    Javascript高级程序设计——客户端检测
    学习javascript系列之变量
  • 原文地址:https://www.cnblogs.com/Andya/p/12560672.html
Copyright © 2020-2023  润新知