一、简介

Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作 。

Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。

同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。

通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。

(Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。)

常见Stream Source生成方式

数据和集合获取

1)Collection.stream()

2)Collection.parallelStream()

3)Arrays.stream(T array) or Stream.of()

BufferedReader获取

java.io.BufferedReader.lines()

Stream常用操作

Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。

Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。

Intermediate:

map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

Terminal:

forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

二、Stream使用样例

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.Test;
import org.mockito.internal.matchers.CompareTo; public class StreamTest { /**
* 构造流的几种常见方法
*/
@Test
public void createStream() { // 通过数组获取Stream
String[] strs = new String[] { "a", "b", "c" };
Stream<String> s1 = Stream.of(strs);
Stream<String> s2 = Arrays.stream(strs);
Stream<String> s3 = Stream.of("a", "b", "c");
// 通过集合
List<String> strLists = Arrays.asList("a", "b", "c");
Stream<String> s4 = strLists.stream(); // 需要注意的是,对于基本数值型,目前有三种对应的包装类型 Stream:
// IntStream、LongStream、DoubleStream。当然我们也可以用 Stream<Integer>、Stream<Long>
// >、Stream<Double>,
// 但是 boxing 和 unboxing 会很耗时,所以特别为这三种基本数值型提供了对应的 Stream。
IntStream.of(new int[] { 1, 2, 3 }).forEach(System.out::println);
IntStream.range(1, 3).forEach(System.out::println);
IntStream.rangeClosed(1, 3).forEach(System.out::println);
} /**
* 流转换为其它数据结构
*/
@Test
public void streamToOther() {
// 转换成Array
Stream<String> s1 = Stream.of("a", "b", "c");
String[] strArray = s1.toArray(String[]::new);
// 转换成Collection
Stream<String> s2 = Stream.of("a", "b", "c");
List<String> list1 = s2.collect(Collectors.toList());
Stream<String> s3 = Stream.of("a", "b", "c");
List<String> list2 = s3.collect(Collectors.toCollection(ArrayList<String>::new));
Stream<String> s4 = Stream.of("a", "b", "c", "c");
Set<String> set1 = s4.collect(Collectors.toSet());
Stream<String> s5 = Stream.of("a", "b", "c");
Stack stack1 = s5.collect(Collectors.toCollection(Stack::new));
// 转换成String
Stream<String> s6 = Stream.of("a", "b", "c");
String str = s6.collect(Collectors.joining()).toString();
} /**
* Stream常用操作
*/
@Test
public void streamOperate() { // map 转换大写
Arrays.asList("lucy", "mark", "zhangsan").stream().map(String::toUpperCase)
.forEach(w -> System.out.println(w));
// map 求平方
Arrays.asList(1, 2, 5, 9).stream().map(n -> n * n).forEach(w -> System.out.println(w)); // flatMap 把 input Stream 中的层级结构扁平化.map是1对1,当有1对多的时候可以用flatMap转换成1对1
// 下面最终的stream 中只有数字了,flatMap把List打散
Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9))
.flatMap(s -> s.stream()).forEach(System.out::print); // filter 对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream。
// 过滤小于等于3的数据
Stream.of(1, 2, 3, 4, 5, 6).filter(n -> n > 3).forEach(System.out::print); // forEach 方法接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式
// forEach 是 terminal 操作.即执行该Stream就被消费掉了,不可以再使用
Stream.of(1, 2, 3, 4, 5, 6).forEach(System.out::print); // peek 对每个元素执行操作并返回一个新的 Stream
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList()); //findFirst 它总是返回 Stream 的第一个元素
Stream.of(1, 2, 3, 4, 5, 6).findFirst().ifPresent(System.out::println); //这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则,
//和前面 Stream 的第一个、第二个、第 n 个元素组合。
//从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce
//也有没有起始值的情况,这时会把 Stream 的前面两个元素组合起来,返回的是 Optional。
//求和(有初始值)
System.out.println(Stream.of(1, 2, 3, 4, 5, 6).reduce(0,(a,b) -> a+b));
//求和(无初始值)
System.out.println(Stream.of(1, 2, 3, 4, 5, 6).reduce(Integer::sum).get());
//拼接字符串
System.out.println(Stream.of("a","b","c").reduce("",String::concat));
// 求最小值,minValue = -3.0
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min)); //limit/skip limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素
Stream.of(1, 2, 3, 4, 5, 6).limit(3).forEach(System.out::println);
Stream.of(1, 2, 3, 4, 5, 6).skip(3).forEach(System.out::println); //sorted:对 Stream 的排序通过 sorted 进行,它比数组的排序更强之处在于你可以首先对 Stream
//进行各类 map、filter、limit、skip
//甚至 distinct 来减少元素数量后,再排序,这能帮助程序明显缩短执行时间。
//根据字符串长度排序
Stream.of("one", "two", "three", "four").sorted((w1,w2) -> w1.length()-w2.length())
.forEach(System.out::println); //Match
//allMatch:Stream 中全部元素符合传入的 predicate,返回 true
//anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
//noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
//它们都不是要遍历全部元素才能返回结果。例如 allMatch 只要一个元素不满足条件,
//就 skip 剩下的所有元素,返回 false。
//判断数组里是否有大于9的数据
System.out.println(Stream.of(1, 2, 3, 4, 5, 6).allMatch(n -> n>9)); //java.util.stream.Collectors 类的主要作用就是辅助进行各类有用的 reduction 操作,
//例如转变输出为 Collection,把 Stream 元素进行归组。
class Person{
public Person(String name,int age) {
this.name = name;
this.age = age;
}
private String name;
private int age;
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
} }
// 按年龄分组
List<Person> persons = Arrays.asList(new Person("1",1),
new Person("1",1),new Person("1",2),new Person("1",3));
Map<Integer, List<Person>> personGroup = persons.stream()
.collect(Collectors.groupingBy(Person::getAge));
personGroup.keySet().stream().forEach(w -> System.out.println(personGroup.get(w)));
} }

参考资料:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/

StreamAPI的更多相关文章

  1. Lambda学习---StreamApi使用

    package com.zx; import com.zx.entity.Book; import org.junit.Test; import java.time.LocalDate; import ...

  2. Java8新特性——StreamAPI(二)

    1. 收集器简介 收集器用来将经过筛选.映射的流进行最后的整理,可以使得最后的结果以不同的形式展现. collect方法即为收集器,它接收Collector接口的实现作为具体收集器的收集方法. Col ...

  3. Java8新特性——StreamAPI(一)

    1. 流的基本概念 1.1 什么是流? 流是Java8引入的全新概念,它用来处理集合中的数据,暂且可以把它理解为一种高级集合. 众所周知,集合操作非常麻烦,若要对集合进行筛选.投影,需要写大量的代码, ...

  4. jdk8中的StreamAPI

    1.实体类 package com.zy.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.D ...

  5. 项目记事【StreamAPI】:使用 StreamAPI 简化对 Collection 的操作

    最近项目里有这么一段代码,我在做 code-review 的时候,觉得可以使用 Java8 StreamAPI 简化一下. 这里先看一下代码(不是源码,一些敏感信息被我用其他类替代了): privat ...

  6. Java8新特性——StreamAPI 的使用

    StreamAPI的说明 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API. Stream API ( java.util.stream) 把真正的 ...

  7. 关于Java8:StreamAPI的一点记录

    关于 Stream ,Functional Interface 的一点记录 stream对于集合操作的便捷度提升: import java.util.ArrayList; import java.ut ...

  8. 使用java8的StreamAPI对集合计算进行代码重构

    方法: 查询出所有部门成员中年龄大于30的员工姓名 部门对象: 员工对象: 模拟数据: private static List<Dept> list=new ArrayList<De ...

  9. 二、StreamAPI

    一.Stream是什么? 是数据通道,用于操作数据源(集合.数组等)所生成的元素序列.集合讲的是数据,流讲的是计算. 注意: Stream不会存储元素. Stream不会改变源对象.相反,他们会返回一 ...

  10. jdk8 StreamApi

    List<User> userList=new ArrayList<>(); userList.add(User.builder().age().name()).build() ...

随机推荐

  1. Xilinx Zynq FPGA Boards板

    Xilinx Zynq FPGA Boards板 Xilinx Zynq FPGA Boards 介绍 Styx是一个易于使用的Zynq开发模块,具有Xilinx的Zynq ZC7020 SoC和FT ...

  2. 如何为嵌入式应用选择适当的SSD

    如何为嵌入式应用选择适当的SSD Selecting the right SSD for evolving embedded applications 变革涉及技术的每一个要素,闪存也不例外.价格下跌 ...

  3. 汉枫Wi-Fi串口服务器HF2211S应用案例

    实现的功能 该模块上电后主动以mobusRTU协议,通过本模块的串口将气体检测仪的4路传感器数据读取 模块上电后连接指定WiFi,通过MQTT协议将读取到的数据以JSON格式推送到指定服务器. 具体细 ...

  4. java并发编程工具类JUC第八篇:ConcurrentHashMap

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  5. 『居善地』接口测试 — 13、Moco框架的使用

    目录 1.Moco框架第一个练习 2.Get方法的Mock实现 3.Post方法的Mock实现 4.请求中加入Cookies 5.请求中加入Header 6.Moco模拟重定向 7.综合练习 8.总结 ...

  6. Mysql_SQLyog 数据库的创建

    1.创建数据库 CREATE DATABASE [IF NOT EXISTS] westos; 2.删除数据库 DROP DATABASE [IF EXISTS] westos; 3.使用数据库 -- ...

  7. Mybatis中9种经典的设计模式!你知道几个?

    虽然我们都知道有23个设计模式,但是大多停留在概念层面,真实开发中很少遇到.Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式. Mybatis至少 ...

  8. App免责声明

    一切移动客户端用户在下载并浏览xxxAPP软件时均被视为已经仔细阅读本条款并完全同意.凡以任何方式使用本APP,或直接.间接使用本APP资料者,均被视为自愿接受本网页相关声明和用户服务协议的约束. x ...

  9. Jenkins CI&CD 自动化发布项目实战(下篇)

    Jenkins CI&CD 自动化发布项目实战(下篇) 作者 刘畅 时间 2020-12-04 实验环境 centos7.5 主机名 ip 服务配置 软件 gitlab 172.16.1.71 ...

  10. scrapy入门到放弃02:整一张架构图,开发一个程序

    前言 Scrapy开门篇写了一些纯理论知识,这第二篇就要直奔主题了.先来讲讲Scrapy的架构,并从零开始开发一个Scrapy爬虫程序. 本篇文章主要阐述Scrapy架构,理清开发流程,掌握基本操作. ...