流是Java API的新成员,它允许以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)。就现在来说,可以把它们看成遍历数据集的高级迭代器。此外,流还可以透明地并行处理,无需写任何多线程代码了!

流的使用一般包括三件事:

•一个数据源(如集合)来执行一个查询;

•一个中间操作链,形成一条流的流水线;

•一个终端操作,执行流水线,并能生成结果。

流方法

含义

示例

filter

(中间操作)该操作会接受一个谓词(一个返回boolean的函数)作为参数,并返回一个包括所有符合谓词的元素的流。

List<Dish> vegetarianMenu = menu.stream()

.filter(Dish::isVegetarian)

.collect(toList());

System.out.println(vegetarianMenu);

distinct

(中间操作)返回一个元素各异(根据流所生成元素的hashCode和equals方法实现)的流。

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);

numbers.stream()

.filter(i -> i % 2 == 0)

.distinct()

.forEach(System.out::println);

limit

(中间操作)会返回一个不超过给定长度的流。

List<Dish> dishes = menu.stream()

.filter(d -> d.getCalories() > 300)

.limit(3)

.collect(toList());

System.out.println(dishes);

skip

(中间操作)返回一个扔掉了前n个元素的流。

List<Dish> dishes = menu.stream()

.filter(d -> d.getCalories() > 300)

.skip(2)

.collect(toList());

System.out.println(dishes);

map

(中间操作)接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素(使用映射一词,是因为它和转换类似,但其中的细微差别在于它是“创建一个新版本”而不是去“修改”)。

List<String> dishNames = menu.stream()

.map(Dish::getName)

.collect(toList());

System.out.println(dishNames);

flatMap

(中间操作)使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。所有使用map(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流。

List<String> words = Arrays.asList("Goodbye", "World");

List<String> uniqueCharacters = words.stream()

.map(w -> w.split(""))

.flatMap(Arrays::stream)

.distinct()

.collect(Collectors.toList());

System.out.println(uniqueCharacters);

sorted

(中间操作)返回排序后的流

List<String> traderStr = menu.stream()

.map(transaction -> transaction.getName())

.sorted()

.collect(toList());

System.out.println(traderStr);

anyMatch

(终端操作)可以回答“流中是否有一个元素能匹配给定的谓词”。

if (menu.stream().anyMatch(Dish::isVegetarian)) {

System.out.println("The menu is (somewhat) vegetarian friendly!!");

}

allMatch

(终端操作)会看看流中的元素是否都能匹配给定的谓词。

boolean isHealthy = menu.stream()

.allMatch(d -> d.getCalories() < 1000);

System.out.println(isHealthy);

noneMatch

(终端操作)可以确保流中没有任何元素与给定的谓词匹配。

boolean isHealthy = menu.stream()

.noneMatch(d -> d.getCalories() >= 1000);

System.out.println(isHealthy);

findAny

(终端操作)将返回当前流中的任意元素。

Optional<Dish> dish = menu.stream()

.filter(Dish::isVegetarian)

.findAny();

System.out.println(dish);

findFirst

(终端操作)有些流有一个出现顺序(encounter order)来指定流中项目出现的逻辑顺序(比如由List或排序好的数据列生成的流)。对于这种流,可能想要找到第一个元素。

List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);

Optional<Integer> firstSquareDivisibleByThree = someNumbers.stream()

.map(x -> x * x)

.filter(x -> x % 3 == 0)

.findFirst();

System.out.println(firstSquareDivisibleByThree);

forEach

(终端操作)遍历流

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);

numbers.stream()

.filter(i -> i % 2 == 0)

.distinct()

.forEach(System.out::println);

collect

(终端操作)收集器

List<String> traderStr = menu.stream()

.map(transaction -> transaction.getName())

.sorted()

.collect(toList());

reduce

(终端操作)归约reduce接受两个参数:

•一个初始值,这里是0;

•一个BinaryOperator<T>来将两个元素结合起来产生一个新值,这里我们用的是lambda (a, b) -> a + b。

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);

int sum = numbers.stream().reduce(0, (a, b) -> a + b);

System.out.println(sum);

count

(终端操作)返回此流中元素的计数。

long evenNumbers = IntStream.rangeClosed(1, 100)

.filter(n -> n % 2 == 0)

.count();

System.out.println(evenNumbers);

•可以使用filter、distinct、skip和limit对流做筛选和切片。

•可以使用map和flatMap提取或转换流中的元素。

•可以使用findFirst和findAny方法查找流中的元素。可以用allMatch、noneMatch和anyMatch方法让流匹配给定的谓词。

•这些方法都利用了短路:找到结果就立即停止计算;没有必要处理整个流。

•可以利用reduce方法将流中所有的元素迭代合并成一个结果,例如求和或查找最大元素。

•filter和map等操作是无状态的,它们并不存储任何状态。reduce等操作要存储状态才能计算出一个值。sorted和distinct等操作也要存储状态,因为它们需要把流中的所有元素缓存起来才能返回一个新的流。这种操作称为有状态操作。

•流有三种基本的原始类型特化:IntStream、DoubleStream和LongStream。它们的操作也有相应的特化。

•流不仅可以从集合创建,也可从值、数组、文件以及iterate与generate等特定方法创建。

•无限流是没有固定大小的流。

附:示例中用到的类

package lambdasinaction.chap4;
import java.util.*; public class Dish { private final String name;
private final boolean vegetarian;
private final int calories;
private final Type type; public Dish(String name, boolean vegetarian, int calories, Type type) {
this.name = name;
this.vegetarian = vegetarian;
this.calories = calories;
this.type = type;
} public String getName() {
return name;
} public boolean isVegetarian() {
return vegetarian;
} public int getCalories() {
return calories;
} public Type getType() {
return type;
} public enum Type { MEAT, FISH, OTHER } @Override
public String toString() {
return name;
} public static final List<Dish> menu =
Arrays.asList( new Dish("pork", false, 800, Dish.Type.MEAT),
new Dish("beef", false, 700, Dish.Type.MEAT),
new Dish("chicken", false, 400, Dish.Type.MEAT),
new Dish("french fries", true, 530, Dish.Type.OTHER),
new Dish("rice", true, 350, Dish.Type.OTHER),
new Dish("season fruit", true, 120, Dish.Type.OTHER),
new Dish("pizza", true, 550, Dish.Type.OTHER),
new Dish("prawns", false, 400, Dish.Type.FISH),
new Dish("salmon", false, 450, Dish.Type.FISH));
}

参考:java8实战

Java8 Stream流方法的更多相关文章

  1. 【转】Java8 Stream 流详解

      当我第一次阅读 Java8 中的 Stream API 时,说实话,我非常困惑,因为它的名字听起来与 Java I0 框架中的 InputStream 和 OutputStream 非常类似.但是 ...

  2. Java8 Stream流

    第三章 Stream流 <Java8 Stream编码实战>的代码全部在https://github.com/yu-linfeng/BlogRepositories/tree/master ...

  3. 关于Java8 Stream流的利与弊 Java初学者,大神勿喷

    题目需求: 1:第一个队伍只要名字为3个字成员的姓名,存储到新集合 2:第一个队伍筛选之后只要前3人:存储到一个新集合 3:第2个队伍只要姓张的成员姓名:存储到一个新集合 4:第2个队伍不要前2人,存 ...

  4. Java8 Stream流API常用操作

    Java版本现在已经发布到JDK13了,目前公司还是用的JDK8,还是有必要了解一些JDK8的新特性的,例如优雅判空的Optional类,操作集合的Stream流,函数式编程等等;这里就按操作例举一些 ...

  5. Java8——Stream流式操作的一点小总结

    我发现,自从我学了Stream流式操作之后,工作中使用到的频率还是挺高的,因为stream配合着lambda表达式或者双冒号(::)使用真的是优雅到了极致!今天就简单分(搬)享(运)一下我对strea ...

  6. 【JDK8】Java8 Stream流API常用操作

    Java版本现在已经发布到JDK13了,目前公司还是用的JDK8,还是有必要了解一些JDK8的新特性的,例如优雅判空的Optional类,操作集合的Stream流,函数式编程等等;这里就按操作例举一些 ...

  7. Java8 - Stream流:让你的集合变得更简单!

    前段时间,在公司熟悉新代码,发现好多都是新代码,全是 Java8语法,之前没有了解过,一直在专研技术的深度,却忘了最初的语法,所以,今天总结下Stream ,算是一份自己理解,不会很深入,就讲讲常用的 ...

  8. java8 stream 流 例子

    Trader raoul = new Trader("Raoul", "Cambridge"); Trader mario = new Trader(" ...

  9. Java8 Stream 流使用场景和常用操作

    JAVA8内置的函数式编程接口应用场景和方式 pojo类对象和默认创建list的方法 import lombok.AllArgsConstructor; import lombok.Data; imp ...

随机推荐

  1. react中IOS手机里面两个input同时存在时,聚焦focus失效解决办法

    最近在做webapp搜索功能时,用到两个input同时存在时,轻点input聚焦时,ios手机软键盘弹起又失效,一直在寻找合理的解决办法,现在最简单的总结回顾: <一>bug显示 < ...

  2. 【原创】STM32低功耗模式及中断唤醒(基于BMI160及RTC)的研究

    预研目标 六轴静止时,终端进入低功耗模式:六轴震动时,终端正常工作模式,从而极大减少非工作时的电流消耗. 解决方案 机器静止时,依据六轴算法,CPU进入休眠(停止)模式:机器工作时,触发六轴中断唤醒C ...

  3. RippleNet: Propagating User Preferences on the Knowledge Graph for Recommender Systems

    一.摘要 为了解决协同过滤的稀疏性和冷启动问题,社交网络或项目属性等辅助信息被用来提高推荐性能. 考虑到知识图谱是边信息的来源,为了解决现有的基于嵌入和基于路径的知识图谱感知重构方法的局限性,本文提出 ...

  4. 【Selenium-WebDriver实战篇】ScreenRecorder的实际输出路径设置(转)

    参考:https://www.cnblogs.com/yongfeiuall/p/4134139.html 我们可以用以下方式在Selenium Webdriver中capture video. 基本 ...

  5. 分享STM32 FLASH 擦除(以及防止误擦除程序代码)、写入

    编译环境:我用的是(Keil)MDK4.7.2   stm32库版本:我用的是3.5.0一.本文不对FLASH的基础知识做详细的介绍,不懂得地方请查阅有关资料. 对STM32 内部FLASH进行编程操 ...

  6. 我的ImageIO.write ByteArrayOutputStream为什么这么慢?

    File.createTempFile(prefix, suffix),创建一个临时文件,再使用完之后清理即可.但是遇到如下两个坑: String prefix = "temp"; ...

  7. prisma 已经支持mongodb了

    好久没有关注prisma 的版本迭代了,记得在去年12月份左右的时候,mongodb 在github 上还只是一个草案, 官方文档也没有相关的详细介绍,今天留意了下,居然已经支持了,还是很给力的(my ...

  8. 2-开发共享版APP(接入指南)-设备接入说明:快速接入

    https://www.cnblogs.com/yangfengwu/p/11249674.html 该APP安装包下载链接: http://www.mnif.cn/appapk/IotDevelop ...

  9. javascript之命名空间方法封装

    详细代码如下: Object.prototype.namespace= function(name){ var parts = name.split('.'); var current = this; ...

  10. Android入门教程(八)

    关注我,每天都有优质技术文章推送,工作,学习累了的时候放松一下自己. 本篇文章同步微信公众号  欢迎大家关注我的微信公众号:「醉翁猫咪」 今天讲讲安卓入门(八),讲讲Android的简介,如何搭建An ...