Java流处理stream使用详解

目录
  • 基本流
    • 中间操作与终端操作
    • 一些常见的终端操作
  • 进阶流
    • 筛选各异的元素
    • 截断
    • 跳过元素
  • 映射流
    • map
    • flatMap
    • 匹配
    • 全匹配与非全匹配
  • Optional
    • findAny
    • findFirst
  • 归约
    • 求和
    • 归约相关阐发
  • 数值流
    • boxed
    • range
  • 构建流

基本流

foreach 实现了外部迭代,它是建立于集合的基础上;

stream 流实现的是内部迭代

中间操作与终端操作

对任意集合使用 stream() 方法来使用流操作来对其进行内部迭代;

中间操作:流水线上的中间操作,他会返回一个 stream

终端操作:一般位于流水线末尾,输出一个非 stream 类型的值

这是下方代码的完整运行过程:

  1. 首先使用 stream 方法使用流来处理集合 names
  2. 使用过滤器 filter,过滤出字符串中含有字符 a 的字符串
  3. distinct 进行去重
  4. toList 将以上所有中间操作过后得到的结果进行汇总,转换成 list 并输出
public static void main(String[] args) {
    List<String> strings = new ArrayList<>();
    strings.add("asd");
    strings.add("asd");
    strings.add("qwe");
    List<String> names = strings.stream()
            // 过滤
            .filter(d -> {
                return d.contains("a");
            })
            // 去重
            .distinct()
            // 转换成列表
            .toList();
    for (String name : names) System.out.println(name); // 输出:asd
}

一些常见的终端操作

foreach:消费流中所有元素并使用 lambda,该操作返回 void

count:返回流中的元素个数,返回类型为 long

collect:把流处理结果返回成一个集合,譬如 toList 方法

进阶流

筛选各异的元素

distinct 进行去重

public static void main(String[] args) {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 1, 2, 4, 2, 2);
    numbers.stream()
            .filter(i -> i % 2 == 0)
            .distinct()
            .forEach(System.out::println);
}

截断

limit,做多返回前 n 个元素

public static void main(String[] args) {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 1, 2, 4, 2, 2);
    numbers.stream()
            .limit(3)
            .forEach(System.out::println);
}

跳过元素

skip(4) 表示跳过前四个元素,并返回后面所有的元素;

由于代码都差不多,这里不做过多演示

映射流

map

map 接收一个函数作为参数,他将对集合中的每个元素应用该函数,并返回该函数规定的值;

如下代码使用 map 获取了每个 dish 的名称并返回它,由此生成了由 dishname 构成的列表

public static void main(String[] args) {
    List<Dish> dishes = new ArrayList<>();
    dishes.add(new Dish("apple", true, 120, Dish.Type.FRUIT));
    dishes.add(new Dish("pork", false, 900, Dish.Type.MEAT));
    dishes.add(new Dish("fish", false, 400, Dish.Type.FISH));
    List<String> dishNames = dishes.stream()
            .map(Dish::getName)
            .toList();
    dishes.forEach(System.out::println);
}

flatMap

map 是将每个元素都映射成了一个流;

flatMap 是将每个元素都放如同一个流中!

以下代码实现:提取单词表中出现的单词;

Arrays.stream 可以将集合转换成流的形式;

应当首先应用 map,将元素进行映射后,在使用 flatMap 把这些映射完毕的元素全部装入一个统一的流里面!

public static void main(String[] args) {
    // 创建单词表
    String[] words = {"goodbye", "hello", "night"};
    // 将单词表转换成流的形式
    Stream<String> swords = Arrays.stream(words);
    // 首先使用map,将所有字母都一一分割来开
    List<String> strings = swords.map(word -> word.split(""))
            // 使用扁平map,将提取到的字母装入一个流中
            .flatMap(Arrays::stream)
            // 字母去重
            .distinct()
            // 转换成列表
            .toList();
    strings.forEach(System.out::println);
}

匹配

anyMatch 能应答:流中是否有至少有一个元素能匹配所给定的谓词(方法引用)

public static void main(String[] args) {
    List<Dish> dishes = Menu.getMenu();
    if(dishes.stream().anyMatch(Dish::isVegetarian)){
        System.out.println("至少有一个素菜!");
    }
}

全匹配与非全匹配

allMatch 方法检查谓词能否匹配所有元素;

noneMatch 方法作用与 allMatch 方法完全相反;

Optional

findAny

findAny 方法默认返回一个 Optional<T>

ifPresent 会在值存在的时候执行后面的 lambda 函数

public static void main(String[] args) {
    List<Dish> dishes = Menu.getMenu();
    dishes.stream()
            .filter(Dish::isVegetarian)
            .findAny()
            .ifPresent(d -> System.out.println(d.getName()));
}

findFirst

顾名思义,找到集合中的第一个元素

归约

求和

下方展示了三种求和方式:

  1. 直接使用 arrays 函数自带的 sum 方法求和;
  2. 使用 reduce,参数一表示初始值,参数二为对值的操作
  3. 同样使用 reduce,但是引入了谓词!
public static void main(String[] args) {
    int[] nums = {1, 2, 3, 4, 5};
    int sum = Arrays.stream(nums).sum();
    int sum2 = Arrays.stream(nums)
            .reduce(0, (a, b) -> a + b);
    int sum3 = Arrays.stream(nums)
            .reduce(0, Integer::sum);
}

归约相关阐发

map+reduce 常被作为一种形式来进行并行化;

使用 reduce 进行的迭代被内部抽象化掉了,所以有益于并行的执行;

parallelStream 可以方便的进行并行操作,但是也带来了同步不安全的隐患;

数值流

使用 mapToInt 返回特化的 IntStream

public static void main(String[] args) {
    List<Dish> dishes = Menu.getMenu();
    int sum = dishes.stream()
            .mapToInt(Dish::getCalories)
            .sum();
}

boxed

将某个特化流转换成一般流,可以使用 boxed 方法

IntStream is = dishes.stream().mapToInt(Dish::getCalories);
Stream<Integer> sis = is.boxed();

range

针对特化流 IntStream 和 LongStream,他们均有 range 和 rangeClose 方法;

range:遍历范围内所有数字除了右边界数字

rangeClose:遍历包含右边界的所有范围数字

下面代码展示了获取 1-100 内所有偶数的个数

IntStream evenNumbers = IntStream.rangeClosed(1,100)
        .filter(n->n%2==0);
System.out.println(evenNumbers.count());

构建流

创建流的三种方式

Stream.of(xxx) 通过数值直接构建;

Arrays.stream() 数组创建;

File.lines() 通过获取的文件内容创建;

到此这篇关于Java流处理stream使用详解的文章就介绍到这了,更多相关Java stream内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java8 Stream流的常用方法汇总

    目录 1.快速创建List (1).new一个list,一个一个添加 (2).Stream流:创建动态list,可以添加元素 (3).如果创建一个固定长度的list,可以使用Arrays.asList(…args)直接返回一个list 2.取对象的某一列: (1).遍历 (2).Stream流:map 3.过滤,或者说是根据一个判断条件筛选出目标对象 (1).遍历加 if (2).Stream流:filter 4.分组 (1).遍历加 if (2).Stream流:groupingBy 5.求和

  • Java 8 Stream 优雅地处理数据

    目录 Stream流 Stream流是什么,为什么要用它 Stream流的基础使用 简单综合案例 传统方法 Stream流式处理方法 获取流 根据Collection获取流 根据Map获取流 根据数组获取流 常用方法 逐一处理:forEach 方法签名 基本使用 筛选:filter 方法签名 基本使用 映射:map 方法签名 基本使用 统计个数:count 方法签名 基本使用 取用前几个:limit 方法签名 基本使用 跳过前几个:skip 方法签名 基本使用 组合:concat 方法签名 基本

  • Java Stream流的常见生成和操作方法总结

    目录 一.Stream流简单示例 二.Stream流常见生成方式 三.Stream流中间操作方法 filter代码示例 limit&skip代码示例 concat&distinct代码示例 sorted代码示例 map&mapToInt代码示例 一.Stream流简单示例 需求: 按照要求集合创建和遍历 创建一个结合,存储多个字符串元素 把集合中所有以"张"开头的元素存储到一个新的集合 把"张"开头的集合中的长度为3的元素存储到一个新的集合

  • Java8 Stream教程之collect()的技巧

    目录 前言 正文 第一个小玩法 将集合通过Stream.collect() 转换成其他集合/数组: 第二个小玩法 聚合(求和.最小.最大.平均值.分组) 总结 前言 本身我是一个比较偏向少使用Stream的人,因为调试比较不方便. 但是, 不得不说,stream确实会给我们编码带来便捷. 正文 Stream流 其实操作分三大块 : 创建 处理 收集 我今天想分享的是 收集 这part的玩法. OK,开始结合代码示例一起玩下: lombok依赖引入,代码简洁一点: <dependency> &l

  • Java 8中 Stream小知识小技巧方法梳理

    目录 前言 只能遍历的一次 Stream 那么为什么流只能遍历一次呢? 流操作 中间操作 终端操作 前言 上篇只是简单的动手操作操作了流(stream),那 stream 到底是什么呢? 官方的简短定义:“从支持数据处理操作的源生成的元素序列” 分成三部分: 元素序列:你可以简单将它类比于一样,不过集合说的是数据的集合,而 stream 重点在于表达计算.如我们之前说到的 filter.map.sorted.limit等等 源:昨天我提到,如果了解过 Liunx 管道命令的朋友们,会知道,Liu

  • 一文详解Java中的Stream的汇总和分组操作

    目录 前言 一.查找流中的最大值和最小值 二.汇总 三.连接字符串 四.分组 1.分组 2.多级分组 3.按子组数据进行划分 后记 前言 在前面的文章中其实大家也已经看到我使用过collect(Collectors.toList()) 将数据最后汇总成一个 List 集合. 但其实还可以转换成Integer.Map.Set 集合等. 一.查找流中的最大值和最小值 static List<Student> students = new ArrayList<>(); ​ static

  • Java基础之Stream流原理与用法详解

    目录 一.接口设计 二.创建操作 三.中间操作 四.最终操作 五.Collect收集 Stream简化元素计算 一.接口设计 从Java1.8开始提出了Stream流的概念,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式:依旧先看核心接口的设计: BaseStream:基础接口,声明了流管理的核心方法: Stream:核心接口,声明了流操作的核心方法,其他接口为指定类型的适配: 基础案例:通过指定元素的值,返回一个序列流,元素的内容是字符串,并转换为Long类型,最终计算求和结果并

  • Java 中如何使用 stream 流

    目录 前言 一.筛选和切片 1.1.筛选 filter 1.2.去重 distinct 1.3.切片 limit 1.4.跳过元素 skip 1.5.排序 sorted 1.6.小结与综合应用 二.映射 map 三.查找和匹配 3.1.匹配 anyMatch.allMatch和noneMatch 方法 3.2.查找 findAny 与 findFirst 3.3.小结 四.归约 4.1.元素求和 reduce 后记 前言 如果你了解过 Liunx ,了解过 Liunx 的中管道命令 | ,那么你

  • Java流处理stream使用详解

    目录 基本流 中间操作与终端操作 一些常见的终端操作 进阶流 筛选各异的元素 截断 跳过元素 映射流 map flatMap 匹配 全匹配与非全匹配 Optional findAny findFirst 归约 求和 归约相关阐发 数值流 boxed range 构建流 基本流 foreach 实现了外部迭代,它是建立于集合的基础上: stream 流实现的是内部迭代 中间操作与终端操作 对任意集合使用 stream() 方法来使用流操作来对其进行内部迭代: 中间操作:流水线上的中间操作,他会返回

  • Java8特性之用Stream流代替For循环操作详解

    目录 准备一个实体类 准备一个List集合 传统的for循环 使用Stream流 先声明筛选条件,在遍历 Stream操作 嵌套循环(2层) 准备一个实体类 public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int get

  • Java中IO流 RandomAccessFile类实例详解

    Java中IO流 RandomAccessFile类实例详解 RandomAccessFile java提供的对文件内容的访问,既可以读文件,也可以写文件. 支持随机访问文件,可以访问文件的任意位置. java文件模型,在硬盘上的文件是byte byte byte存储的,是数据的集合 打开文件,有两种模式,"rw"读写."r"只读:RandomAccessFile raf = new RandomAccessFile(file, "rw");,文

  • Java打印流原理及实例详解

    这篇文章主要介绍了Java打印流原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 平时我们在控制台打印输出,是调用print方法和println方法完成的,这两个方法都来自于java.io.PrintStream类,该类能够方便地打印各种数据类型的值,是一种便捷的输岀方式. PrintStream类 PrintStream类,为其他输出流添加了功能,使他们能够方便的打印各种数据值表示格式. PrintStream类的特点: 只负责数

  • Java使用FileInputStream流读取文件示例详解

    一.File流概念 JAVA中针对文件的读写操作设置了一系列的流,其中主要有FileInputStream,FileOutputStream,FileReader,FileWriter四种最为常用的流 二.FileInputStream 1)FileInputStream概念  FileInputStream流被称为文件字节输入流,意思指对文件数据以字节的形式进行读取操作如读取图片视频等 2)构造方法 2.1)通过打开与File类对象代表的实际文件的链接来创建FileInputStream流对象

  • 浅谈JAVA中输入输出流实例详解

    java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象.在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流....本文的目的是为大家介绍JAVA中输入输出流实例详解. 流的层次结构 定义:        java将读取数据对象成为输入流,能向其写入的对象叫输出流.结构图如下: 1.输入输出: 输入/输出(Input/Output)是指对某

  • Kotlin下Rxjava的基础用法及流式调用示例详解

    目录 前言 基础用法 fromXXX create interval & timer 指定线程 observeOn & subscribeOn Flowable 流式调用 背压 前言 万事开头难,写文章也是,现在越来越不知道开头怎么写了,所以在前言中,简单介绍下RxJava吧,第一次听说还是以前做Android开发的时候,那时候好多库中都使用了Rxjava,而在网络请求中,也有很多都是使用Rxjava去写,但自己却没怎么在项目中写过,而在搜索资料中发现,微信中搜rxjava时,最多介绍他的

  • java 深拷贝与浅拷贝机制详解

     java 深拷贝与浅拷贝机制详解 概要: 在Java中,拷贝分为深拷贝和浅拷贝两种.java在公共超类Object中实现了一种叫做clone的方法,这种方法clone出来的新对象为浅拷贝,而通过自己定义的clone方法为深拷贝. (一)Object中clone方法 如果我们new出一个新对象,用一个声明去引用它,之后又用另一个声明去引用前一个声明,那么最后的结果是:这两个声明的变量将指向同一个对象,一处被改全部被改.如果我们想创建一个对象的copy,这个copy和对象的各种属性完全相同,而且修

  • Java中File的实例详解

    Java中File的实例详解 File 代表文件或者目录的类 构造函数 File(File parent,String child)---代表了指定父目录下的指定的子文件或者子目录 File(String pathname)---代表了指定路径对应的文件或者目录对象 重要方法 创建 createNewFile()---只能用来创建文件,并且一次只能创建一个文件,要求文件存储的目录必须真实存在 mkdir()---只能用来创建目录,不能用来创建多层目录 mkdirs()---创建多层目录 删除 d

随机推荐