Stream

从迭代到Stream操作

流表面上看起来与集合相似,允许你转换和检索数据。然而,两者却有显著的不同:

  • 流不储存元素。元素储存在底层的集合或者按需生成。
  • 流操作不改变它们的源数据。
  • 如果可能的话,Stream操作就是延迟执行的。这意味着直到需要结果时,方法才会执行。

Stream遵循"做什么,而不是怎么去做"的原则。
比如,例子:计算集合中长度大于3的总数

String str = "aaa,cccc,dddd,eeee,ffff";  
List<String> words = List.of(str.split(","));  
//迭代  
int count = 0;  
for (String w : words) {  
    if(w.length() > 3) count++;  
}

//使用流时,只需要描述需要做的事情
long count = words.stream().filter(w -> w.length() >3).count();

//采用并行流,并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。并行流只有对大型数据集才能显示出优势。
long count = words.parallelStream().filter(w -> w.length() >3).count();

//如果words对象已经是流,可以使用parallel()并行执行。
long count = words.parallel().filter(w -> w.length() >3).count();

创建Stream

转换成流

  • 面对集合,使用Collection接口的stream方法
  • 面对数组,使用Stream.of();

创建一个不包含任何元素的Stream
Stream<String> silence = Stream.empty()

创建无限Stream的静态方法

  • 创建一个常量值,使用generate()
//创建一个常量值
Stream.generate(() -> "Echo");
//创建一个随机数
Stream.generate(Math :: random);
  • 创建一个例如0 1 2 3...... 这样的无穷序列,可使用iterate(),
Stream.iterate(BigInteger.ZERO , n->n.add(BigInteger.ONE));

转换流

filter

转换成一个匹配一定条件的新流。
stream().filter(w -> w.length() > 12);

map

将一个流中的值进行某种形式的转换。
比如:将所有单词转换成小写形式

List<String> words = ...
Stream<String> lowercaseWords = words.stream().map(String :: toLowerCase);
flatMap
public static Stream<String> codePoints(String s){  
    List<String> result = new ArrayList<>();  
    int i =0;  
    while (i < s.length())  
    {  
        int j = s.offsetByCodePoints(i, 1);  
        result.add(s.substring(i,j));  
        i = j;  
    }  
    return result.stream();  
}

String[] strWords = {"words"};  
//将得到一个包含多个流的流
Stream<Stream<String>> result1 = Stream.of(strWords).map(w -> codePoints(w));  

//将得到一个只包含字符串的流
Stream<String> result2 = Stream.of(strWords).flatMap(w -> codePoints(w));

提取子流和组合流

stream.limit()

返回一个包含n个元素的新流(如果原始流的长度小于n,则会返回原始流)。
Stream.generate(Math :: random).limit(100);

stream.skip()

它会丢弃前n个元素。
Stream.of("a","b","c").skip(1);

stream.takeWhile(predicate)

从流接收所有元素,当predicate为true时,停止接收。

Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())  
        .forEach(System.out::print);
stream.dropWhile()

当条件判断为true时,丢弃元素。该方法生成一个流,该流包含了所以条件判断为false的元素。

Stream.of("a","b","c","","e","f").dropWhile(s->s.isEmpty()).forEach(System.out::print);
Stream.concat()

可以将两个流连接起来。
Stream.concat(Stream.of("a","b","c"),Stream.of("e","f")).forEach(System.out::print);

其他流转换

distinct()

去重

sorted()

排序
Stream.of("gg","b","c","","e","f").sorted(Comparator.comparing(String::length).reversed());

peek()

生成一个与原先流一样有着相同元素的新流,但是每当检索一个元素时函数就调用一次。对调试来说非常方便。
如果你想知道流的流水线之特定地方发生了什么,则添加如下代码:

.peek(x ->{
    return;})
并在第二行设置断点。

简单归约

从流数据中获得答案,归约是终止操作,比如count()、max()、min()等。

//大部分方法会返回一个Optional<T>类型的值,它可能会封装返回值,也可能表示没有返回(当流为空时)。
String str = "b,o,a,t";  
List<String> words = List.of(str.split(","));  
Optional<String> largest = words.stream().max(String::compareToIgnoreCase);  
System.out.println(largest.orElse(""));

Optional类型

有效的使用Optional的关键在于:使用一个要么如果值不存在,产生另一个替代值; 要么如果值存在,使用该值的方法。

如果值不存在,产生另一个替代值

  • 使用一个默认值
String result = optionalString.orElse("");
  • 调用代码来计算默认值
String result = optionalString.orElseGet(() -> System.getProperty("myapp.default"));
  • 抛出一个异常
String result = optionalString.orElseThrow(IllegalStateException :: new);

当值存在,使用它

  • 使用ifPresent(),如果Optional值存在的话,则它会被传递给函数。当使用它给函数传递Option值时,函数返回值会丢失。
optionalValue.ifPresent(v -> Process v);
//例如:
 List<String> list = new ArrayList<>();  
 optionalValue.ifPresent(v ->list.add(v));
 //或者
 optionalValue.ifPresent(list::add);
  • ifPresentOrElse(),当Optional有值时执行某个任务,没有值时执行另外一个任务。
optionalValue.ifPresentOrElse(v -> Process v, ()->执行其他任务);
  • 使用map(),可以处理函数结果。
//如果存在一个值,则返回一个可选的,描述将给定的映射函数应用于该值的结果(就像通过ofNullable一样),否则返回一个空的可选的。如果映射函数返回空结果,则此方法返回空的可选结果。
Optional<Boolean> data = optionalValue.map(list::add);

收集结果

遍历流
stream.forEach(System.out :: printIn);

将结果收集到一个数据结构中

  • 收集到数组中
String[] result = stream.toArray(String[] :: new);
//stream.toArray()会返回Object[]类型,可以将类型传递给数组的构造函数,来获取相应类型的数组
  • 收集到另一个目标容器里
//收集到list中
List<String> result = stream.collect(Collectors.toList());
//收集到set中
Set<String> result = stream.collect(Collectors.toSet());
//收集到哪种集合中
HashSet<String> result = stream.collect(Collectors.toCollection(HashSet::new));
//如果你想将流中的所有字符串拼接并收集起来,并且流包含字符串以外的对象
String result = stream.map(Object::toString).collect(Collectors.joining());
//也可以在元素之间插入分隔符
String result = stream.map(Object::toString).collect(Collectors.joining(","));
//收集到Map中
Stream<String> stream = Stream.of("aaa", "bbbb", "ccccc");  
Map<String, Integer> map = stream.collect(Collectors.toMap(Function.identity(), String:: length));
//数据视图结果:{aaa=3, ccccc=5, bbbb=4}
//Function.identity()返回一个输出跟输入一样的Lambda表达式对象,等价于形如`t -> t`形式的Lambda表达式

基本类型流

Stream类库提供了IntStream、LongStream和DoubleStream类型,分别表示原始int流、原始long流和原始double流,而不用进行包装。

Image placeholder
czc74520
未设置
  89人点赞

没有讨论,发表一下自己的看法吧

推荐文章
php常用字符串查找函数strstr()与strpos()实例分析

这篇文章主要介绍了php常用字符串查找函数strstr()与strpos(),结合具体实例形式分析了php字符串查找函数strstr()与strpos()的具体功能、用法、区别及相关操作注意事项,需要

String 类的 substring () 方法

截取字符串,在java语言中的用法 1.substring(intbeginIndex) 返回一个新字符串,它是此字符串的一个子字符串。该子字符串始于指定索引处的字符,一直到此字符串末尾。 参数:

【Kubernetes系列】第5篇 Ingress controller – traefik组件介绍

1.概述为了能够让Ingress资源能够工作,在Kubernetes集群中必须至少有一个运行中的ingresscontroller组件。也就是说如果在kubernetes集群中没有一个ingressc

Spring Cloud Stream整合Kafka

引入依赖 org.springframework.cloud spring-cloud-stream-binder-kafka 或 org.springframework.cloud spr

Java 8 Stream Api 中的 peek 操作

1.前言 在Java8StreamAPI详细使用指南中讲述了Java8StreamAPI中map操作和flatMap操作的区别。然后有小伙伴告诉我peek操作也能实现元素的处理。但是你知道map和pe

了解Node.js中的流(Stream)

Node.js中的流(Stream)是出了名的难用甚至是难以理解。用DominicTarr的话来说:“流是Node中最好的,也是最容易被误解的想法。”即使是Redux的创建者和React.js的核心团

工具分享:Linux tree 命令安装和使用

说明tree命令是一个比较实用文件系统查看工具,如下图,可以阶梯式地罗列某个目录下的所有子目录:如何安装?RHEL/CentOS下:#yuminstalltree-yDebian/Ubuntu, Mi

Java并发编程,深入理解ReentrantLock

ReentrantLock简介ReentrantLock重入锁, 是实现Lock接口的一个类 ,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次

124. Binary Tree Maximum Path Sum - 二叉树中的最大路径和

1描述给定一个非空二叉树,返回其最大路径和。路径:一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。用例 输入:[1,2,3] 1 /\ 23 输出:6输入:

element-ui tree懒加载时获取节点DOM

tree提供的方法貌似没有可以直接获取节点DOM,或者点击勾选节点响应函数参数node其实只是传入data的数据对象,拿不到DOM,得想想法子来获取之事情是这样的:最近做一个表单,要能勾选一个二级的下

02.4. struct 类型

struct Go语言中,也和C或者其他语言一样,我们可以声明新的类型,作为其它类型的属性或字段的容器。例如,我们可以创建一个自定义类型person代表一个人的实体。这个实体拥有属性:姓名和年龄。这样

1.0. 抽象工厂模式(Abstract Factory)

1.1.1.目的 在不指定具体类的情况下创建一系列相关或依赖对象。通常创建的类都实现相同的接口。抽象工厂的客户并不关心这些对象是如何创建的,它只是知道它们是如何一起运行的。 1.1.2.UML图 1

phpstrom 快捷键,老是记不住哇! 记一下记一下!

老是记不住哇!记一下记一下! Esc键编辑器(从工具窗口)F2(Shift+F2)下/上高亮错误或警告快速定位F3向下查找关键字出现位置F4查找变量来源F5复制文件/文件夹F6移动F11切换书签F12

bootstrap和vue的区别是什么?

Bootstrap是美国Twitter公司的设计师MarkOtto和JacobThornton合作基于HTML、CSS、JavaScript开发的简洁、直观、强悍的前端开发框架,使得Web开发更加快捷

BootstrapVue快速入门

Vue.js是一个流行的JavaScript库,用于在短时间内开发原型。这包括用户界面、前端应用、静态网页和本机移动应用。它以易用的语法和简单的数据绑定功能而闻名。最近,Vue.js生态系统发布了一个

数据库中间件分片算法之stringhash

前言又是一个夜黑风高的晚上,带上无线耳机听一曲。突然很感慨一句话:生活就像心电图,一帆风顺就证明你挂了。就如同我们干运维的,觉得很简单的事情,有时候能干出无限可能。还是言归正传吧,这一次我们来说说st

jquery easyui和bootstrap的区别是什么?

JQueryEasyUIJQueryEasyUI是一组基于jQuery的UI插件集合体,而jQueryEasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者不需要编写复

JSON.parse和JSON.stringify的巧用

JSON.parse和JSON.stringify是对json数据的转换,在js中使用的频率还是非常高的,比如localStorage,cookie中对复合型数据的存储,与服务器进行数据交互的格式转换

Python可视化 | Seaborn5分钟入门(四)——stripplot和swarmplot

微信公众号:「Python读财」如有问题或建议,请公众号留言Seaborn是基于matplotlib的Python可视化库。它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matp

QString之arg

QString的arg接口主要用于字符串组合的功能。arg接口列表QStringarg(constQString&a,intfieldWidth=0,QCharfillChar=QLatin1Char

JSON.parse和JSON.stringify的巧用

JSON.stringify()是将一个JavaScript值(对象或者数组)转换为一个json字符串,如果指定了replacer是一个函数,则可以选择性地替换值,或者如果指定了replacer是一个

Bootstrap基础笔记

322222222222222222222222222

Bootstrap基础笔记

![](https://cdn2.lmonkey.com/uploads/2020-10-14-08-34-202880123

PostgreSQL DBA(31) – Backup&Recovery#4(搭建流复制)

PostgreSQL通过流复制StreamingReplication可轻松实现高可用HA环境的搭建.本节简单介绍了搭建流复制环境的基本步骤.Step1主库:创建用户 创建复制用户replicator

request爬虫post 请求

json意义:JSON,全称是JavaScriptObjectNotation。它是基于baiJavaScript编程语言ECMA-2623rdEdition-December1999标准的一种轻量级