Java8新特性——流式操作

本文详细介绍了Java8中的流式操作,包括流的概念、如何获取流、常用的流操作如forEach、filter、map、count、limit、skip和concat。通过实例展示了如何使用流简化集合处理,强调了流的内部迭代、延迟执行和短路特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

说道Stream流很容易想到I/O Stream,而实际上,Stream流不是I/O的一种,而是Lambda所带来的
的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库该有的弊端。

几乎所有的集合(Collection接口或Map接口等)都支持直接或者间接的遍历操作,而我们需要对集合中的元素进行操作的时候,除了必须的添加、删除、获取外,典型的就是集合遍历。

例如:

public class Demo01ForEach {
   
    public static void main(String[] args) {
   
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        for (String name : list) {
   
            System.out.println(name);
        }
    }
}

这一段非常简单的集合遍历操作:对集合中的每一个字符串都激进型打印输出操作。

循环遍历的弊端

Java8中Lambda让我们可以更加专注于做什么(what),而不是怎么做(How)看上述代码,可以发现:
for循环的语法就是“怎么做”
for循环的循环体才是“做什么”
为什么使用循环?因为要进行遍历,但循环是遍历的唯一方式么?遍历是指每一个元素逐一进行处理,而并不是从第一个到最后一个顺次处理的循环。
试想一下,如果希望对集合中的元素进行筛选过滤:

  1. 将集合A根据条件一 过滤为子集B
  2. 然后再根据条件二 过滤子集C

那怎么办?在Java8之前的做法可能为:

//Java8 之前过滤操作
    private static void test() {
   
        List<String> list=new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        List<String> zhangList=new ArrayList<>();
        for(String name:list){
   
            if(name.startsWith("张")){
   
                zhangList.add(name);
            }
        }
        List<String> shortList=new ArrayList<>();
        for(String name:zhangList){
   
            if(name.length()==3){
   
                zhangList.add(name);
            }
        }
        for (String s : shortList) {
   
            System.out.println(s);
        }
    }

这段代码中含有三个循环,每一个作用不同,
每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么,并不是。
循环是做事情的方式,而不是目的。另一方面,使用线性循环就意味着只能遍历一次。如果希望再次遍历,只能再使用另一个循环从头开始。
那,Lambda的衍生物Stream能给我们带来怎么更加简洁的写法呢?

Stream更加简洁写法

先看一段代码:

 List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.stream()
                .filter(s->s.startsWith("张"))
                .filter(s->s.length()==3)
                .forEach(System.out::println);

直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印。

流式思想概述

当需要对多个元素进行操作(特别是多步操作)的时候,考虑到性能及便利性,我们应该首先拼好一个模型步骤方案,然后再按照方案去执行。

想象一下图中展示了过滤、映射、跳过、计数等多步操作,这是一种集合元素的处理方案,而方案就是一种“函数模型”。每一个步骤都是一个流,调用指定的方法,可以从一个流模型转换为另一个流模型。

备注:“Stream流”其实是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)

Stream(流)是一个来自数据源的元素队列

数据源流的来源。可以是集合,数组等。
和以前的Collection操作不同,Stream操作还有两个基础的特征:

  • Pipelining:中间操作都会返回流对象本身。这样多个操作可以串联成一个管道,如同流式风格,这样做可以对操作进行优化,比如延迟执行和短路。
  • 内部迭代:以前对集合遍历都是通过Iterator或者增强for的方式,显示的在集合外部进行迭代,这叫做外部迭代。Stream提供了内部迭代的方式,流可以直接调用遍历方法。

当使用一个流的时候,通常包括三个基本步骤:获取一个数据源 ->数据转换-> 执行操作获取想要的结果&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值