• Stream流
  • 一 : Stream流的介绍
  • 二 : 获取Stream流的方式
  • 三 : Stream流中的常用方法
    • 1.forEach(终结方法)
    • 2.过滤:filter
    • 3.映射(转换):map
    • 4.统计个数:count(终结方法)
    • 5.取用前几个(截取):limit
    • 6.跳过前几个元素:skip
    • 7.组合(合并流):concat
    • 8.筛选:distinct
    • 9.映射(打开后再转换):flatMap
    • 10.自然排序:sorted
    • 11.定制排序:sorted(Comparator com)
    • 12.检测匹配(终结方法):
    • 13.查找元素(终结方法)
    • 14.查找最大最小值(终结方法)
    • 15.规约(终结方法)
    • 16.收集(终结方法)
    • 17.迭代:iterate
    • 18.查看:peek
  • Srtream流中方法的使用练习

转载自:
https://blog.csdn.net/m0_46434219/article/details/109049369
https://blog.csdn.net/weixin_45785893/article/details/109733327

Stream流

一 : Stream流的介绍

  1. stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果;
  2. stream不会改变数据源,通常情况下会产生一个新的集合;
  3. stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
  4. stream操作分为终端操作和中间操作,那么这两者分别代表什么呢?
    终端操作:会消费流,这种操作会产生一个结果的,如果一个流被消费过了,那它就不能被重用的。
    中间操作:中间操作会产生另一个流。因此中间操作可以用来创建执行一系列动作的管道。一个特别需要注意的点是:中间操作不是立即发生的。相反,当在中间操作创建的新流上执行完终端操作后,中间操作指定的操作才会发生。所以中间操作是延迟发生的,中间操作的延迟行为主要是让流API能够更加高效地执行。
  5. stream不可复用,对一个已经进行过终端操作的流再次调用,会抛出异常。

二 : 获取Stream流的方式

java.util.stream.Stream 是Java 8新加入的流接口。(并不是一个函数式接口
获取一个流非常简单,有以下几种常用的方式:

  • 所有的 Collection 集合都可以通过 stream 默认方法获取流(顺序流);
  • 所有的 Collection 集合都可以通过parallelStream获取并行流
  • Stream 接口的静态方法 of 可以获取数组对应的流。
  • Arrays的静态方法stream也可以获取流

根据Collection获取流

public static void main(String[] args) {List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();Set<String> set = new HashSet<>();Stream<String> stream2 = set.stream();Vector<String> vector = new Vector<>();// ...
}

根据Map获取流

public static void main(String[] args) {Map<String, String> map = new HashMap<>();Stream<String> keyStream = map.keySet().stream();Stream<String> valueStream = map.values().stream();Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
}

根据数组获取流
如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以 Stream 接口中提供了静态方法of ,使用很简单:

public static void main(String[] args) {//使用 Stream.ofString[] array = { "张无忌", "张翠山", "张三丰", "张一元" };Stream<String> stream = Stream.of(array);//使用Arrays的静态方法Arrays.stream(array)
}

三 : Stream流中的常用方法

这些方法可以被分成两种:

  • 延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为延迟方法。)
  • 终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调用。本小节中,终结方法包括 count 和 forEach 方法。

1.forEach(终结方法)

用于遍历的方法,参数传入一个函数式接口:Consumer

public static void main(String[] args) {Stream<String> stream = Stream.of("张无忌", "张三丰", "周芷若");stream.forEach(name‐> System.out.println(name));
}

2.过滤:filter

可以用于过滤

可以通过 filter 方法将一个流转换成另一个子集流。

public static void main(String[] args) {//创建一个流Stream<String> stream = Stream.of("张三丰", "刘德华", "张国荣", "彭于晏", "纳什", "吴彦祖", "吴绮蓉");//对流中元素过滤,只要姓张的人Stream<String> stream2 = stream.filter(name -> {return name.startsWith("张");});//遍历过滤后的流stream2.forEach(name -> System.out.println(name));}

3.映射(转换):map

如果需要将流中的元素映射到另一个流中,可以使用 map 方法。

该接口需要一个 Function 函数式接口参数

此前我们已经学习过 java.util.stream.Function 函数式接口,其中唯一的抽象方法为

R apply(T t);

这可以将一种T类型转换成为R类型,而这种转换的动作,就称为“映射"

map使用方法

/*** stream流的map方法练习* map方法可以将流中的元素映射到另一个流中* map方法的参数是一个Function函数式接口*/@Testpublic void test(){//创建一个流,里面是字符串类型的整数Stream<String> stream1 = Stream.of("2", "32", "2", "33", "2");//把stream1流中的整数全部转成int类型Stream<Integer> stream2 = stream1.map((String s) -> {return Integer.parseInt(s);});//遍历stream2.forEach((i)-> System.out.println(i));}

4.统计个数:count(终结方法)

正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数:

该方法返回一个long值代表元素个数(不再像旧集合那样是int值)。基本使用:

public class Demo09StreamCount {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//筛选姓张的Stream<String> result = original.filter(s ‐> s.startsWith("张"));//输出个数System.out.println(result.count()); // 2}
}

5.取用前几个(截取):limit

limit 方法可以对流进行截取,只取用前n个。

参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。基本使用:

public class Demo10StreamLimit {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//截取前两个Stream<String> result = original.limit(2);System.out.println(result.count()); // 2}
}

6.跳过前几个元素:skip

如果希望跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流:

Stream<T> skip(long n);

如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。基本使用

public class Demo11StreamSkip {public static void main(String[] args) {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");//跳过前两个,返回一个新的流Stream<String> result = original.skip(2);System.out.println(result.count()); // 1}
}

7.组合(合并流):concat

如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat :

public class Demo12StreamConcat {public static void main(String[] args) {Stream<String> streamA = Stream.of("张无忌");Stream<String> streamB = Stream.of("张翠山");//合并成一个新的流Stream<String> result = Stream.concat(streamA, streamB);}
}

8.筛选:distinct

去除流中重复的元素(使用hashcode和equals方法来对比)

9.映射(打开后再转换):flatMap

内部传入一个Function函数式接口,跟map的区别就是这个会把流中的元素打开,再组合成一个新的流

// map和flatMap的练习
public class StreamDemo {@Testpublic void test(){List<String> list = Arrays.asList("aa","bb","cc","dd");// 练习1 (map) 输出的全是大写list.stream().map(s -> s.toUpperCase()).forEach(System.out::println);System.out.println("----------");// 练习2(map)流里还有流,需要两个遍历才行看到里面内容Stream<Stream<Character>> streamStream = list.stream().map(StreamDemo::fromStringToStream);streamStream.forEach(s -> {s.forEach(System.out::println);});System.out.println("---------");// 练习3(flatMap)流里还有流,使用flatMap可以直接把里面的流打开,一次遍历就可以了Stream<Character> characterStream = list.stream().flatMap(StreamDemo::fromStringToStream);characterStream.forEach(System.out::println);}/***  将字符串中的多个字符构成的集合转换为对应的stream* @param str* @return*/public static Stream<Character> fromStringToStream(String str){ArrayList<Character> list = new ArrayList();// 将字符串转成字符数组,并遍历加入list集合for(Character c : str.toCharArray()){list.add(c);}// 返回list集合的stream流return list.stream();}
}

10.自然排序:sorted

看下一条里的代码

11.定制排序:sorted(Comparator com)

 /*** 排序的练习*/@Testpublic void test2(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 按照自然排序integers.stream().sorted().forEach(System.out::println);System.out.println("---------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 定制排序(大到小),需要传入Comparator接口(如果流中的是引用类型,只能用定制排序)// 简写:integers2.stream().sorted((e1,e2) -> e2-e1).forEach(System.out::println);integers2.stream().sorted((e1,e2) -> {return e2-e1;}).forEach(System.out::println);}

12.检测匹配(终结方法):

返回一个Boolean值

是否全部匹配:allMatch

是否至少匹配一个:anyMatch

是否没有匹配的:noneMatch

 /*** 匹配的练习*/@Testpublic void test3(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 判断是否全部大于5boolean b = integers.stream().allMatch(i -> i > 5);// 结束输出falseSystem.out.println(b);System.out.println("-------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 检测是否匹配至少一个元素boolean b1 = integers2.stream().anyMatch(i -> i > 5);// 输出trueSystem.out.println(b1);System.out.println("-------");List<Integer> integers3 = List.of(124, 2, 15, 12, 51, -5, 5);// 检查是否没有匹配的元素boolean b2 = integers3.stream().noneMatch(i -> i > 1000);// 输出true,全部不匹配System.out.println(b2);}

13.查找元素(终结方法)

查找第一个元素:findFirst,返回Optional类型

查找其中一个元素:findAny,返回Optional类型

public void test4(){List<Integer> integers = List.of(124, 2, 15, 12, 51, -5, 5);// 输出第一个元素Optional<Integer> first = integers.stream().findFirst();// 输出结果是Optional[124]System.out.println(first);System.out.println("-------------");List<Integer> integers2 = List.of(124, 2, 15, 12, 51, -5, 5);// 返回其中一个元素Optional<Integer> any = integers2.stream().findAny();System.out.println(any);}

14.查找最大最小值(终结方法)

max(comparator c)

min(comparator c)

 /*** 查找最大最小值*/@Testpublic void test5(){List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));//  查找年龄最大的人Optional<Person> max = list.stream().max((e1, e2) -> e1.getAge() - e2.getAge());// 返回马云,55岁年龄最大System.out.println(max.get());System.out.println("--------");

15.规约(终结方法)

reduce(T identity ,BinaryOperator) 第一个参数是初始值,第二个参数是一个函数式接口

reduce(BinaryOperator) 参数是一个函数式接口

/*** 归约的练习*/@Testpublic void test6(){List<Integer> integers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 求集合里数字的和(归约)reduce第一个参数是初始值。Integer sum = integers.stream().reduce(0, Integer::sum);System.out.println(sum);System.out.println("-------");List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));// 求所有人的工资和(归约)// 不用方法引用写法:Optional<Integer> reduce = list.stream().map(person -> person.getSalary()).reduce((e1, e2) -> e1 + e2);Optional<Integer> reduce = list.stream().map(Person::getSalary).reduce(Integer::sum);// 输出Optional[19937]System.out.println(reduce);}

16.收集(终结方法)

collect(Collector c):将流转化为其他形式,接收一个Collector接口的实现

/*** 收集的练习*/@Testpublic void test7(){List<Person> list = new ArrayList<>();list.add(new Person("马化腾",25,3000));list.add(new Person("李彦宏",27,2545));list.add(new Person("雷军",35,4515));list.add(new Person("马云",55,9877));// 把年龄大于30岁的人,转成一个list集合List<Person> collect = list.stream().filter(person -> person.getAge() > 30).collect(Collectors.toList());// 遍历输出(输出雷军和马云)for (Person person : collect) {System.out.println(person);}System.out.println("----------");List<Person> list2 = new ArrayList<>();list2.add(new Person("马化腾",25,3000));list2.add(new Person("李彦宏",27,2545));list2.add(new Person("雷军",35,4515));list2.add(new Person("马云",55,9877));// 把姓马的人,转成Set集合Set<Person> set = list2.stream().filter(person -> person.getName().startsWith("马")).collect(Collectors.toSet());// 输出马云和马化腾set.forEach(System.out::println);}

17.迭代:iterate

可以使用Stream.iterate创建流值,即所谓的无限流。

//Stream.iterate(initial value, next value)Stream.iterate(0, n -> n + 1).limit(5).forEach(x -> System.out.println(x));

输出:

0
1
2
3
4

18.查看:peek

peek接收的是一个Consumer函数,peek 操作会按照 Consumer 函数提供的逻辑去消费流中的每一个元素,同时有可能改变元素内部的一些属性

@Testpublic void test1(){List<String> collect = Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.println("查看一下刚过滤出的值:" + e)).map(String::toUpperCase).peek(e -> System.out.println("查看一下转大写之后的值:" + e)).collect(Collectors.toList());System.out.println("-----分割线-----");// 遍历过滤后的集合for (String s : collect) {System.out.println(s);}}

输出:

查看一下刚过滤出的值:three
查看一下转大写之后的值:THREE
查看一下刚过滤出的值:four
查看一下转大写之后的值:FOUR
-----分割线-----
THREE
FOUR

Srtream流中方法的使用练习

/***     1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。*    2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。*   3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。*    4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。*   5. 将两个队伍合并为一个队伍;存储到一个新集合中。*  6. 根据姓名创建 Person 对象;存储到一个新集合中。*  7. 打印整个队伍的Person对象信息。*/
public class Demo3 {public static void main(String[] args) {//第一支队伍ArrayList<String> one = new ArrayList<>();one.add("迪丽热巴");one.add("宋远桥");one.add("苏星河");one.add("石破天");one.add("石中玉");one.add("老子");one.add("庄子");one.add("洪七公");//第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。//第一个队伍筛选之后只要前3个人;存储到一个新集合中。Stream<String> stream = one.stream();Stream<String> stream1 = stream.filter(name -> name.length() == 3).limit(3);//第二支队伍ArrayList<String> two = new ArrayList<>();two.add("古力娜扎");two.add("张无忌");two.add("赵丽颖");two.add("张三丰");two.add("尼古拉斯赵四");two.add("张天爱");two.add("张二狗");//第二个队伍只要姓张的成员姓名;存储到一个新集合中。//第二个队伍筛选之后不要前2个人;存储到一个新集合中。Stream<String> stream2 = two.stream();Stream<String> stream3 = stream2.filter(name -> name.startsWith("张")).skip(2);//合并两个队伍Stream<String> concat = Stream.concat(stream1, stream3);//把合并后的队伍根据姓名创建Person对象,并存入新的集合中,然后打印concat.map(name -> new Person(name)).forEach(p -> System.out.println(p));}
}

stream流详解(JDK1.8的特性)相关推荐

  1. Java8新特性Stream流详解

    陈老老老板 说明:新的专栏,本专栏专门讲Java8新特性,把平时遇到的问题与Java8的写法进行总结,需要注意的地方都标红了,一起加油. 本文是介绍Java8新特性Stream流常用方法超详细教学 说 ...

  2. Java - Stream流详解

    文章目录 前言 大家好,好久不见了,最近由于实训的影响导致拖更了,在更新这一次估计javaSE基本上就算是完结了,还有一些落下的后面也会补上的,下次见面就是数据结构了 尽情期待吧!那么就让我们步入St ...

  3. Java中的Stream流详解

    JDK8 Stream详解 概念 Stream是Java8 API的新成员,它允许以声明性方式处理数据集合 . 特点 (1)代码简洁:函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告 ...

  4. java8 stream遍历_Java8新特性:Stream流详解

    1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...

  5. Java--Stream流详解

    Stream是Java 8 API添加的一个新的抽象,称为流Stream,以一种声明性方式处理数据集合(侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式) Stream流是从支持数据处理操 ...

  6. 【java8新特性】——Stream API详解(二)

    一.简介 java8新添加了一个特性:流Stream.Stream让开发者能够以一种声明的方式处理数据源(集合.数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation ...

  7. Java 中IO流详解(附实例代码/面试题)

    Java I/O流详解 前言 一.I/O流是什么? 二.IO流分类: 1. 流程图: io流对象 2. io流的优缺点: 3. io 流Java中用途有哪些? 三.一些 io 实例 四.面试题: 前言 ...

  8. Java 8 Stream API详解--转

    原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java 8引入 ...

  9. Java 8 Stream API详解

    Java 8 Stream API详解 一.Stream API介绍 Java 8引入了全新的Stream API,此Stream与Java I/O包里的InputStream和OutputStrea ...

最新文章

  1. C# 生成随机字符串
  2. 算法刷题-数论-组合数、快速幂、逆元、递推求组合数、逆元求组合数
  3. jquery的2.0.3版本源码系列(2):21行-94行定义了一些变量和函数 jQuery=function(){}
  4. python中continue用法案例_Python continue语句实例用法
  5. 孵化业务快速落地与优化
  6. 【转】vc6.0移植到VS2010遇到的问题,散分给大家,虽然分不多,各位帮忙
  7. influxdb数据备份和恢复
  8. 分享17个网页设计中字体排版的优秀示例
  9. 20155308 2017-2018-1 《信息安全系统设计基础》第十三周学习总结
  10. 铁塔形变预警监测装置
  11. Android 测试点归纳总结
  12. 【时序】时间序列领域的 GAN 模型综述论文笔记
  13. 汉字读音表GB2312版 (共7809个汉字)
  14. BP神经网络的初步介绍
  15. css flash布局_跳过简介-CSS3是新的Flash
  16. 64位计算机最大寻址,为什么说32位操作系统的寻址空间是4G
  17. vue页面跳转打开新的窗口
  18. MPLS virtual private network PE-CE之间的路由协议(OSPF)
  19. 【暴力枚举】速算游戏 fun.pas/c/cpp
  20. Mysql 8.0安装 Navicat for MySQL 下载安装及使用教程

热门文章

  1. FoveaBox 笔记
  2. parentNode 与 parentElement
  3. 糖尿病患者怎样养成良好习惯
  4. UGO模型 ACL特殊权限
  5. 赖世雄精准美语发音指南下载地址
  6. excel 第9讲:countif函数
  7. HDU - Mophues(莫比乌斯反演)
  8. 一个Excel表格转换问题(横变竖,竖变横)
  9. 分布式服务架构与微服务架构概念的区别与联系是怎样的
  10. the URL contained a potentially malicious String “//“