一回顾与说明

经过前面发布的三章java8的博客,你就懂得了我们为什么要用Lamda表达式,Lamda表达式的原理与函数式接口的关系,从Lamda表达式到方法引用和构造引用。

想要学Stream流你必须对前面的知识熟悉并且掌握,今天我们来讲一下Lamda表达式的进阶学习,Stream流API。

二什么是Stream流

流想比大家都认识,比如食物的包装过程,先要有个食物员提供食物,食物经过加工处理,添加调料,...,包装,组装。简单的说普通的流就像工厂的流水线一样。

Stream流是可以能够用声明的方式来操作集合(可以想象sql操作数据库那样),可以将其看作遍历数据集的高级迭代器。在操作流的时候我们就可以将其比喻成工厂中的流水线。

三 流的优势

流有什么优势呢?流竟然是一种迭代器,那它与集合的for循环有什么区别,为什么我们要用流来迭代呢?

  • 集合中存放的数据都是计算好的,我们用一次集合遍历,必须有始有终,不能中断。Stream流像视频流一样我们可以先加载一部分,看一部分,中途还能暂停中断离开;相比之集合流更加灵活
  • 流的迭代遍历是一次性的,意味着一个流你只能迭代一次,完成迭代这个流就被消费掉。
  • 流相比于for循环是内部迭代的,我们只要给出具体的函数操作流就ok,而for循环是外部迭代。

四 Stream流的操作过程

Stream流跟生产线上的流类式有提供源,操作,终止三个过程



常见的中间操作流:



常见的结束流:​

五常见的StreamAPI

初始化车辆信息

    public List<Car> InitCar(){
ArrayList<Car> carList = new ArrayList<>();
Car car1 = new Car("100", "black", "中国", 20);
Car car2 = new Car("101", "gray", "中国", 30);
Car car3 = new Car("102", "yello", "中国", 50);
Car car4 = new Car("103", "silvery", "英国", 20);
Car car5 = new Car("104", "red", "英国", 30);
carList.add(car1);
carList.add(car2);
carList.add(car3);
carList.add(car4);
carList.add(car5);
return carList;
}

1 筛选

filter函数就是过滤出流中我们需要的元素--中间操作

    @Test
public void filterTest(){
// 初始化车辆
List<Car> cars = carFunFactory.InitCar();
// 筛选车辆时黑色的车
List<Car> result = cars.stream()
.filter(car -> car.getColor().equals("black"))
.collect(Collectors.toList());
//[Car(code=100, color=black, factory=中国, price=20.0)]
System.out.println(result); }

2排序

sorted函数默认会升序排序元素--中间操纵

   @Test
public void sortTest(){
int[] ints = {0, 5, 7, 6, 15, 13, 27};
Arrays.stream(ints).sorted().forEach(System.out::println);
}

3 去重

distinct去掉重复的元素--中间操作

    @Test
public void distinctTest(){
int[] ints = {5,6,5,6,27};
// 5 6 27
Arrays.stream(ints).distinct().forEach(System.out::println);
}

4 截断

limit函数限值流的元素--中间操作

   @Test
public void limitTest(){
int[] ints = {5,6,5,6,27};
// 5 6
Arrays.stream(ints).limit(2).forEach(System.out::println);
}

5跳跃

skip函数跳过n个元素--中间操作

    @Test
public void skipTest(){
int[] ints = {5,6,5,6,27};
// 27
Arrays.stream(ints).skip(4).forEach(System.out::println);
}

6映射

map是转换函数,接受一个函数为参数,将其映射在每一个元素上,转换成新的元素。--中间操作

    @Test
public void mapTest(){
// 初始化车辆
List<Car> cars = carFunFactory.InitCar();
// 只获得车的价格
cars.stream().limit(1)
.map(Car::getPrice)
.forEach(System.out::println);//20.0
}

7流的扁平化

flatMap函数能将中间多个流的内容合并为一个流。--中间操作

    @Test
public void flatMapTest(){
String[] array = {"youku1327"};
// 存放的是一个个数组 [Ljava.lang.String;@61f3fbb8
Arrays.stream(array).map(s -> s.split(""))
.forEach(System.out::print);
// 将一个个数组流合并为一个流输出:youku1327
Arrays.stream(array).map(s -> s.split(""))
.flatMap(Arrays::stream)
.forEach(System.out::print);
}

8任意匹配

anyMatch函数任意匹配到流中的一个元素返回真。---终止操作

    @Test
public void anyMatchTest(){
// 初始化车辆
List<Car> cars = carFunFactory.InitCar();
// 任意匹配黄色的车
boolean yello = cars.stream()
.anyMatch(car -> car.getColor().equals("yello"));
System.out.println(yello);//true
}

9 完全匹配

allMatch函数完全匹配流中的元素返回真。--终止操作

   @Test
public void allMatchTest(){
// 初始化车辆
List<Car> cars = carFunFactory.InitCar();
// 完全匹配黄色的车
boolean yello = cars.stream()
.allMatch(car -> car.getColor().equals("yello"));
System.out.println(yello);//false
}

10非匹配

noneMatch函数没有匹配到流中的任意一个元素返回为真。------终止操作

    @Test
public void noneMatchTest(){
// 初始化车辆
List<Car> cars = carFunFactory.InitCar();
// 不是youku1327这个颜色的车
boolean yello = cars.stream()
.noneMatch(car -> car.getColor().equals("youku1327"));
System.out.println(yello);//true
}

11任意寻找流中的一个元素

findAny函数任意查找流中的一个元素返回。---终止操作

    @Test
public void findAnyTest(){
// 初始化车辆
List<Car> cars = carFunFactory.InitCar();
// 不是youku1327这个颜色的车
Optional<Car> anyCar = cars.stream().findAny();
Car car = anyCar.orElse(new Car("141", 50));
// Car(code=100, color=black, factory=中国, price=20.0)
System.out.println(car);
}

12 寻找流中的第一个元素

findFirst函数寻找流中的第一个元素。--------终止操作

    @Test
public void findFirstTest(){
// 初始化车辆
List<Car> cars = carFunFactory.InitCar();
// 不是youku1327这个颜色的车
Optional<Car> anyCar = cars.stream().findFirst();
// Car(code=100, color=black, factory=中国, price=20.0)
System.out.println(anyCar.get());
}

13 归约

reduce函数将前一个入参数和后一个入参进行操作后的值做为第下一次操作的前一个入参,以此类推。--终止操作

    @Test
public void reduceTest(){
int[] ints = {3,4,5,};
int reduce = Arrays.stream(ints)
.reduce(0, (left, right) -> left + right);
// 求和 12
System.out.println(reduce);
OptionalInt max = Arrays.stream(ints).reduce(Integer::max);
// 求最大值 5
System.out.println(max.getAsInt());
OptionalInt min = Arrays.stream(ints).reduce(Integer::min);
// 求最小值 3
System.out.println(min.getAsInt());
}

14数值流

IntStream 、 DoubleStream 和LongStream ,分别将流中的元素特化为 int 、 long 和 double ,避免自动装箱

。-----中间操作

    @Test
public void numTest(){
int[] ints = {5,6,5,6};
// int流
IntStream intStream = Arrays.stream(ints);
// 6767爱看youku1327
intStream.mapToObj(value -> value+1).forEach(System.out::print);
System.out.println("爱看youku1327");
double[] doubles = {5,6,5,6};
// double流
DoubleStream doubleStream = Arrays.stream(doubles);
//5.06.05.06.0关注youku1327
doubleStream.forEach(System.out::print);
System.out.println("关注youku1327");
// long流
Long[] longs = {5L,6L,5L,6L};
Stream<Long> longStream = Arrays.stream(longs);
long count = longStream.count();
// 4
System.out.println(count); }

15 流转换

boxed函数将数值流转为原始流。-----中间操作

    @Test
public void streamSwapTest(){
int[] ints = {5,6,7};
// 将int流转为原始流
Optional<Integer> first = Arrays.stream(ints).boxed().findFirst();
System.out.println(first.get());//5
// 2.23606797749979 2.449489742783178 2.6457513110645907
Arrays.stream(ints).boxed()
.mapToDouble(s ->Math.sqrt(s))
.forEach(System.out::println);
}

六 构建流

1 数值生成流

    @Test
public void buildStreamByValue(){
Stream<String> stream = Stream.of("关", "注", "微", "信", "公", "众", "号", ":", "youku1327", "谢谢");
//关注微信公众号:youku1327谢谢
stream.map(StringUtils::join).forEach(System.out::print);
}

2 由数组创建流

 @Test
public void skipTest(){
int[] ints = {5,6,5,6,27};
// 27
Arrays.stream(ints).skip(4).forEach(System.out::println);
}

3 由文件创建流

    @Test
public void buildStreamByFile(){
try {
Stream<String> lines = Files.lines(Paths.get("C:\\mydata\\youku1327.txt"), Charset.defaultCharset());
lines.map(s -> s.split(""))
.flatMap(Arrays::stream)
.forEach(System.out::print);//youku1327
} catch (IOException e) {
e.printStackTrace();
}
}

4创建无限流

generate和iterate都是创建无限流,我们要约束一下,以免无线流一直创建元素。

    @Test
public void buildStreamByIterate(){
long count = Stream.iterate(1, integer -> integer + 1)
.limit(100)
.count();
System.out.println(count);//100
}

七 致谢

观看完这一篇stream流API操作基本就可以胜任平常工作中的各种场景,后面会继续更新流的高级操作

最后推一波微信公众号,有兴趣学习的就关注吧。

java8-Stream流API的更多相关文章

  1. Java8 Stream流API常用操作

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

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

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

  3. 【转】Java8 Stream 流详解

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

  4. Java8 Stream流

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

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

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

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

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

  7. Java9系列第6篇-Stream流API的增强

    我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 ...

  8. Java8 Stream流方法

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

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

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

  10. java8 stream 流 例子

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

随机推荐

  1. 2019-10-12,html+php+mysql简单留言板,作业

    php+mysql简易留言板,实现注册,登录,注销,查看留言,删除留言 1,index.html登录页面 代码: <!doctype html> <html> <head ...

  2. 【NHOI2018】字符串变换

    [题目描述] 给你一个全部由大小写字母组成的字符串,你每次可以将一个小写字母变换成对应的大写字母,或把一个大写字母变换成对应的小写字母.请问:至少要进行多少次变换才可以使整个字符串全部由大写字母或全部 ...

  3. 【集训Day1 测试】【USACO】照相

    照相(fairphoto) [题目描述] 有N 头奶牛站在一条数轴上,第 i 头奶牛的位置是 Pi,奶牛不会重叠站在同一个位置, 第i 头奶牛的颜色是 Ci,其中 Ci 要么是字符'G'要么是字符'H ...

  4. python的reduce,map,zip,filter和sorted函数

    一.    reduce(function,Iterable),它的形式和map()函数一样.不过参数function必须有两个参数. reduce()函数作用是:把结果继续和序列的下一个元素做累积计 ...

  5. 内核升级在线安装报错:Could not retrieve mirrorlist http://mirrors.elrepo.org/mirrors-elrepo-kernel.el7 error was14: curl#6 - "Could not resolve host: mirrors.elrepo.org; 未知的错误"

    修改网卡配置 [root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens32 BOOTPROTO="none" ...

  6. Xtrabackup 全备和还原以及增量备份和还原

    目录 MySQL环境介绍 全备和还原 准备备份目录 创建测试数据 全量备份 模拟删除数据 还原数据操作 第一步 备份备份文件 第二步 关闭数据库 第三步 移除数据库的data目录 第四步 恢复前准备 ...

  7. c语言基本数据类型short、int、long、char、float、double大小及命名规则

    C 语言包含的数据类型: 一.数据类型与“模子”short.int.long.char.float.double 这六个关键字代表C 语言里的六种基本数据类型. 怎么去理解它们呢? 举个例子:见过藕煤 ...

  8. apache thrift 和 apache jersey 记录

    几篇好的入门文档链接: 1. Hello World by Thrift Using Java 2. Thrift 实例 Helloworld 3. Thrift版的Hello World 4. Th ...

  9. vue 常用的官网

    vue.js     https://cn.vuejs.org/ v-charts  https://v-charts.js.org/#/                    (图表,地图) web ...

  10. luogu P1356 数列的整数性 |动态规划

    题目描述 对于任意一个整数数列,我们可以在每两个整数中间任意放一个符号'+'或'-',这样就可以构成一个表达式,也就可以计算出表达式的值.比如,现在有一个整数数列:17,5,-2,-15,那么就可以构 ...