Java8 新特性之集合的流式编程

Java8 引入了流式编程,通过Stream API增强集合操作,简化代码。流不是数据结构,而是从数据源获取数据并进行处理的机制。流式编程包括数据源获取、中间操作和最终操作。中间操作如filter、distinct、sorted等,不改变原数据源;最终操作如collect、reduce、forEach等,用于数据整合并关闭流。Collectors工具类提供了多种集合转换方法。
摘要由CSDN通过智能技术生成

一、集合流的概述

1.1 集合的流式编程简介

Stream 是 JDK1.8 之后出现的新特性,也是 JDK1.8 新特性中最值得学习的两种新特性之一。(另外一个是 Lambda 表达式)

Stream 是对集合操作的增强,流不是集合的元素,不是一种数据结构,不负责数据的存储。流更像是一个迭代器,可以单向的遍历一个集合中的每个元素,并且不可循环。

在这里插入图片描述

1.2 集合的流式编程的优点

为什么要用集合的流式编程呢?想必它一定有值得人们去关注的优点。

有些时候,对集合的元素进行操作的时候,需要使用到其他操作的结果。在这个过程中,集合的流式编程可以大幅度的简化代码的数量。将数据源中的数据读取到一个流中,可以对这个流中的数据进行操作(删除、过滤、映射…)。每次的操作结果也是一个流对象,可以对这个流再进行其他的操作。

1.3 使用流式编程的步骤

通常情况下,对集合中的数据使用流式编程,需要经过以下三步:

  1. 获取数据源,将数据源中的数据读取到流中;
  2. 对流中的数据进行各种各样的处理;
  3. 对流中的数据进行整合处理。

在上述三个过程中:对于过程 2,有若干方法可以对流中的数据进行各种各样的操作,并且返回流对象本身,这样的操作,被称为中间操作。对于过程 3,有若干方法可以对流中的数据进行各种处理,并且关闭流,这样的操作,被称为最终操作

在中间操作和最终操作中,基本上所有的方法参数都是函数式接口,可以使用 Lambda 表达式来实现。使用集合的流式编程来简化代码量,需要对 Lambda 表达式做到熟练掌握。

二、数据源的获取

2.1 数据源简介

数据源,顾名思义,就是流中的数据的来源。读取数据源是流式编程的第一步。注意:数据被读取到流中之后,流中进行处理的数据与数据源中的数据没有关系。也就是说,中间操作对流中的数据进行处理、过滤、映射、排序等操作是不会影响到数据源中的数据的。

2.2 数据源的获取

这个过程,实际上是将一个容器中的数据读取到另一个流中。因此无论什么容器作为数据源,读取到流中的方法的返回值一定是一个 Stream。

如下所示为数据源的获取的示例代码:

/**
  * @Description 将集合作为数据源,读取集合中的数据到一个流中
  */
private static void collectionDataSource(){
   
    // 1. 实例化一个集合
    ArrayList<Integer> list = new ArrayList<>();
    // 2. 填充元素到集合中
    Collections.addAll(list, 1, 2, 3, 4, 5);
    // 3. 读取集合中的元素到流中
    Stream<Integer> stream = list.stream();
    System.out.println(stream);
}

/**
  * @Description 将数组作为数据源,读取数组中的数据到一个流中
  */
private static void arrayDataSource(){
   
    // 1. 实例化一个数组
    Integer[] arr = new Integer[]{
   1, 2, 3, 4, 5};
    // 2. 读取数组中的数据到流中
    Stream<Integer> stream = Arrays.stream(arr);
    System.out.println(stream);
}

三、最终操作

3.1 最终操作简介

最终操作就是将流中的数据整合到一起,比如可以存入到一个集合中,也可以直接对流中的数据进行遍历、统计等。通过最终操作,可以从流中提取出来我们想要的信息。

Stream 流的最终操作主要有以下几种:

【注意事项】

之所以叫最终操作,是因为在最终操作结束之后,会关闭这个流,流中所有的数据都会被销毁。如果使用一个已经关闭了的流,会出现异常。

3.2 collect

collect() 方法的作用就是将流中的数据收集到一起,最常见的处理就是将流中的数据存入一个集合中。collect 方法的参数是一个 Collector 接口,而且这个接口并不是一个函数式接口,因此我们可以自定义类来实现这个接口。但是在绝大多数情况下,是不需要我们自定义的,我们借助工具类 Collectors 即可。

【举例说明】

  • 例一:将 List 集合中的数据读取到流中,然后原封不动将流中数据存入 Set 集合中。

    public class StreamDemo_02 {
         
       
       public static void main(String[] args) {
         
           Stream<Integer> stream = getDataSource();
           Set<Integer> set = stream.collect(Collectors.toSet());	// 将 stream 中数据存入 set 集合中
           System.out.println(set);
       }
       /**
        * 获取数据源
        */
       private static Stream<Integer> getDataSource(){
         
           Integer[] list = new Integer[]{
         1, 2, 3, 4, 5};
           return Arrays.stream(list);
       }
    }
    

    运行结果如下:
    在这里插入图片描述

  • 例二:将 List 集合中的数据读取到流中,然后原封不动将流中数据存入 Map 集合中。

    public class StreamDemo_02 {
         
    
        public static void main(String[] args) {
         
            Stream<Integer> stream = getDataSource();
            /**
             * 将数据存入 map 中,这里用到了 lambda 表达式
             * 这里的 Collectors.toMap 的函数原型是:
        	 *	   Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
             *                           		   Function<? super T, ? extends U> valueMapper) 
             * 通过函数原型可以看到,函数的参数都是函数式接口 Function。
             * 其中:参数一为 key 的映射,参数二为 value 的映射。
             * 因此,可以使用 lambda 表达式,将 key 映射为集合元素的字符串形式,将 value 映射为集合元素本身
             */
            Map<String, Integer> map = 
                stream.collect(Collectors.toMap(x -> x.toString(), x -> x));   // 将stream中数据存入map中
            System.out.println(map);
        }
        /**
         * 获取数据源
         */
        private static Stream<Integer> getDataSource(){
         
            Integer[] list = new Integer[]{
         1, 2, 3, 4, 5};
            return Arrays
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值