一.概念

Stream是一种可供流式操作的数据视图有些类似数据库中视图的概念它不改变源数据集合如果对其进行改变的操作它会返回一个新的数据集合。

总的来讲它有三大特性:在之后我们会对照着详细说明

       1、stream不存储数据

       2、stream不改变源数据

       3、stream的延迟执行特性

二.优点

1、代码简洁,函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。

       2、多核友好,Java函数式编程使得编写并行程序从未如此简单,你需要的全部就是调用一下parallel()方法。

三.Stream API常用方法

Stream操作分类
中间操作(Intermediate operations) 无状态(Stateless) unordered() filter() map() mapToInt() mapToLong() mapToDouble() flatMap() flatMapToInt() flatMapToLong() flatMapToDouble() peek()
有状态(Stateful) distinct() sorted() sorted() limit() skip()
结束操作(Terminal operations) 非短路操作 forEach() forEachOrdered() toArray() reduce() collect() max() min() count()
短路操作(short-circuiting) anyMatch() allMatch() noneMatch() findFirst() findAny()

Stream上的所有操作分为两类:中间操作和结束操作,中间操作只是一种标记,只有结束操作才会触发实际计算。

中间操作又可以分为无状态的和有状态的:

无状态中间操作是指元素的处理不受前面元素的影响,而有状态的中间操作必须等到所有元素处理之后才知道最终结果,比如排序是有状态操作,在读取所有元素之前并不能确定排序结果;

结束操作又可以分为短路操作和非短路操作

短路操作是指不用处理全部元素就可以返回结果,比如找到第一个满足条件的元素。之所以要进行如此精细的划分,是因为底层对每一种情况的处理方式不同。

常用中间件

filter:过滤流,过滤流中的元素,返回一个符合条件的Stream

map:转换流,将一种类型的流转换为另外一种流。(mapToInt、mapToLong、mapToDouble 返回int、long、double基本类型对应的Stream)

flatMap:简单的说,就是一个或多个流合并成一个新流。(flatMapToInt、flatMapToLong、flatMapToDouble 返回对应的IntStream、LongStream、DoubleStream流。)

distinct:返回去重的Stream。

sorted:返回一个排序的Stream。

peek:主要用来查看流中元素的数据状态。

limit:返回前n个元素数据组成的Stream。属于短路操作

skip:返回第n个元素后面数据组成的Stream。

结束操作

forEach: 循环操作Stream中数据。

toArray: 返回流中元素对应的数组对象。

reduce: 聚合操作,用来做统计。

collect: 聚合操作,封装目标数据。

min、max、count: 聚合操作,最小值,最大值,总数量。

anyMatch: 短路操作,有一个符合条件返回true。

allMatch: 所有数据都符合条件返回true。

noneMatch: 所有数据都不符合条件返回true。

findFirst: 短路操作,获取第一个元素。

findAny: 短路操作,获取任一元素。

forEachOrdered: 暗元素顺序执行循环操作。

四.常用场景和方法举例

1.迭代

forEach()方法:void forEach(Consumer< ? super T> action);

peek()方法:Stream peek(Consumer< ? super T> action);

List<String> list=...
// 传统for循环
for (String s : list) {
System.out.println(s);
} // 使用forEach(结束操作),对集合的修改不会影响原集合
list.stream().forEach(x -> {
System.out.println(x);
}); // 使用peek(中间操作),对集合的修改也会体现在原集合中
list = list.stream().peek(x -> {
System.out.println(x);
}).collect(Collectors.toList());

2.转换

map()方法:Stream map(Function< ? super T, ? extends R> mapper);

public class Person {
private Integer id;
private String name;
private String sex;
private Integer age;
//提供get,set,和满参构造函数
} public class TestMap {
  public static void main(String[] args) {
    List<Person> persionList = new ArrayList<Person>();
    persionList.add(new Person(1,"张三","男",38));
    persionList.add(new Person(2,"小小","女",2));
    persionList.add(new Person(3,"李四","男",65));
    persionList.add(new Person(4,"王五","女",20));
    persionList.add(new Person(5,"赵六","男",38));
    persionList.add(new Person(6,"大大","男",65));     //1、只取出该集合中所有姓名组成一个新集合
    List<String> nameList=persionList.stream().map(Person::getName).collect(Collectors.toList()); //未去重
    List<String> nameList=persionList.stream().map(Person::getName).distinct().collect(Collectors.toList()); //去重
    System.out.println(nameList.toString());     //2、只取出该集合中所有id组成一个新集合
    List<Integer> idList=persionList.stream().mapToInt(Person::getId).boxed().collect(Collectors.toList());
    System.out.println(idList.toString());     //3、list转map,key值为id,value为Person对象
    Map<Integer, Person> personmap = persionList.stream().collect(Collectors.toMap(Person::getId, person -> person));
    System.out.println(personmap.toString());     //4、list转map,key值为id,value为name
    Map<Integer, String> namemap = persionList.stream().collect(Collectors.toMap(Person::getId, Person::getName));
    System.out.println(namemap.toString());     //5、进行map集合存放,key为age值 value为Person对象 它会把相同age的对象放到一个集合中
    Map<Integer, List<Person>> ageMap = persionList.stream().collect(Collectors.groupingBy(Person::getAge));
    System.out.println(ageMap.toString());     //6、获取最小年龄
    Integer ageMin = persionList.stream().mapToInt(Person::getAge).min().getAsInt();
    System.out.println("最小年龄为: "+ageMin);     //7、获取最大年龄
    Integer ageMax = persionList.stream().mapToInt(Person::getAge).max().getAsInt();
    System.out.println("最大年龄为: "+ageMax);     //8、集合年龄属性求和
    Integer ageAmount = persionList.stream().mapToInt(Person::getAge).sum();
    System.out.println("年龄总和为: "+ageAmount);
  }
}

3.过滤

filter()方法:Stream filter(Predicate< ? super T> predicate);

public class TestFilter {
  public static void main(String[] args) {
    List<Person> persionList = new ArrayList<Person>();
    persionList.add(new Person(1, "张三", "男", 8));
    persionList.add(new Person(2, "小小", "女", 2));
    persionList.add(new Person(3, "李四", "男", 25));
    persionList.add(new Person(4, "王五", "女", 8));
    persionList.add(new Person(5, "赵六", "女", 25));
    persionList.add(new Person(6, "大大", "男", 65));     //1、查找年龄大于20岁的人数
    long age=persionList.stream().filter(p->p.getAge()>20).count();
    System.out.println(age);     //2、查找年龄大于20岁,性别为男的人数
    List<Person> ageList=persionList.stream().filter(p->p.getAge()>20).filter(p->"男".equals(p.getSex())).collect(Collectors.toList());
    System.out.println(ageList.size()); //3、查找年龄大于20岁的男性 或 年龄大于18岁的女性人数
List<Person> ageList=persionList.stream().filter(p -> (p.getAge()>20 && "男".equals(p.getSex())) || (p.getAge()>18 && "女".equals(p.getSex()))).collect(Collectors.toList());
System.out.println(ageList.size());     //4、过滤掉 姓名、性别、年龄 均相同的重复项
    List<Person> ageList=persionList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(p -> p.getName() + ";" + p.getSex() + ";" + p.getAge()))), ArrayList::new));
    System.out.printIn(ageList.size());
  }
}

4.排序

sorted() 排序方法:

public class Test {
public static void main(String[] args) {
List<Person> persionList = new ArrayList<Person>();
persionList.add(new Person(1, "张三", "男", 8));
persionList.add(new Person(2, "小小", "女", 2));
persionList.add(new Person(3, "李四", "男", 25));
persionList.add(new Person(4, "王五", "女", 8));
persionList.add(new Person(5, "赵六", "女", 25));
persionList.add(new Person(6, "大大", "男", 65)); //根据年龄升序
persionList = persionList.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList());
persionList = persionList.stream().sorted(Comparator.comparingInt(x -> x.getAge())).collect(Collectors.toList());
persionList = persionList.stream().sorted((a, b) -> a.getAge().compareTo(b.getAge())).collect(Collectors.toList());
//根据年龄降序
persionList = persionList.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());
persionList = persionList.stream().sorted((a, b) -> b.getAge().compareTo(a.getAge())).collect(Collectors.toList());
//根据年龄降序,年龄相同的再根据id升序
persionList = persionList.stream().sorted(Comparator.comparing(Person::getAge).reversed().thenComparing(Person::getId)).collect(Collectors.toList());
}
}

Java8 Stream —— 更丝滑的集合操作方式的更多相关文章

  1. Node更丝滑的打开方式

    Node更丝滑的打开方式 1. 使用背景 最近前端的一个项目,使用gulp作为工程化.在运行过程中出现如下错误 gulp[3192]: src\node_contextify.cc:628: Asse ...

  2. 让你的app体验更丝滑的11种方法!冲击手机应用榜单Top3指日可待

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由WeTest质量开放平台团队发表于云+社区专栏 一款app除了要有令人惊叹的功能和令人发指交互之外,在性能上也应该追求丝滑的要求,这样 ...

  3. eladmin-plus V2.0.0 发布,单表链式调用更丝滑

    一.项目简介 eladmin的mybatis-plus版本,单表使用链式调用,代码更简洁,调用更便捷.目前更新到2021年7月.项目基于 Spring Boot 2.4.2 . Mybatis-plu ...

  4. 一分钟小知识:scroll-behavior 让你的页面导航滚动更丝滑~

    中午在[掘金]潜水摸鱼,看到这一个沸点,个人已经撸出特效: 下面放上  作者 的 掘金 地址  #掘金沸点# https://juejin.im/pin/5d649eaaf265da19752533d ...

  5. Java 8 新特性-Stream更优雅的处理集合入门

    Java 8 新特性之--Stream 一. 简单介绍 Stream是Java 8提出了的一种新的对集合对象功能的增强.它集合Lambda表达式,对集合提供了一些非常便利,高效的操作,使得代码具有非常 ...

  6. 简洁又快速地处理集合——Java8 Stream(下)

    上一篇文章我讲解 Stream 流的基本原理,以及它与集合的区别关系,讲了那么多抽象的,本篇文章我们开始实战,讲解流的各个方法以及各种操作 没有看过上篇文章的可以先点击进去学习一下 简洁又快速地处理集 ...

  7. 简洁又快速地处理集合——Java8 Stream(上)

    Java 8 发布至今也已经好几年过去,如今 Java 也已经向 11 迈去,但是 Java 8 作出的改变可以说是革命性的,影响足够深远,学习 Java 8 应该是 Java 开发者的必修课. 今天 ...

  8. Java8 Stream:2万字20个实例,玩转集合的筛选、归约、分组、聚合

    点波关注不迷路,一键三连好运连连! 先贴上几个案例,水平高超的同学可以挑战一下: 从员工集合中筛选出salary大于8000的员工,并放置到新的集合里. 统计员工的最高薪资.平均薪资.薪资之和. 将员 ...

  9. 《你还在写sql语句吗?》人生苦短,进入MybatisPlus的丝滑体验

    一.发展历程 依稀记得大学期间,类中写sql语句的日子,一个sql语句占据了大部分时间,到后来hibernate的出现算是解决了这一痛点.工作 后,我们又接触到了mybatis这样的框架,瞬间感觉这个 ...

随机推荐

  1. OutOfMemoryError本地线程不足问题分析

    java.lang.OutOfMemoryError本地线程不足问题 11月份中旬客户方的一个系统突然报内存异常,当时是早上上班的时候碰到该项目的项目经理,还跟该项目的项目经理开玩笑说你们系统上线将近 ...

  2. Redis报错: StackExchange.Redis.RedisServerException: Endpoint 39.105.22.111:7200 serving hashslot 12448 is not reachable at this point of time.

    emmmm……要下班了,简单记录一下. 如果是127.0.0.1:7200报这个错,请移步 https://blog.csdn.net/foreverhot1019/article/details/7 ...

  3. 2019-9-16:渗透测试,基础学习,Linux下软件安装,环境搭建,笔记

    Centos linux下软件安装yum 通过分析rpm包头数据后,自动解决依赖关系,直接云端下载软件,根据不同版本系统获取不同软件信息,按顺序下载rpm包,安装软件yum search 软件名:搜索 ...

  4. C语言与汇编语言混合编程实验

    混合编程方法: 模块链接法 汇编指令嵌入法 1: 模块链接法则 模块链接法是指分别用汇编语言和C语言实现独立的模块(或子程序),再用链接程序把各模块生成的obj文件连接成一个可执行程序. 1:C语言调 ...

  5. JVM学习笔记(1)--运行时数据区域

    运行时数据区域 相对于c,c++.程序设计时,java并不需要手动释放或者创建内存用于存放程序,这的确使得java开发变得容易和轻松,一旦有一天出现了内存泄漏或者内存溢出的问题,如果不了解JVM虚拟机 ...

  6. linuxRAID(软)

    RAID是一种存储机制,英文全名为“RedundantArrays of Inexpensive Disks”,即容错廉价磁盘阵列.RAID可以通过一些技术(硬件或者软件)将多个磁盘整合起来,不仅是一 ...

  7. linux防火墙的相关命令

    一.iptables防火墙(需要安装防火墙sudo apt-get install firewalld命令查看插件)1.基本操作 # 查看防火墙状态 service iptables status # ...

  8. 对 /langversion 无效;必须是 ISO-1、ISO-2、3、4、5 或 Default

    反编译或者.net用更高版本打开时会出现这个问题,解决办法如下: 1.网页版程序,将解决方案中的Web.config中的 /langversion 的值改为指定的值,既可以解决,我这里采用的是默认值, ...

  9. django的开发环境

    推荐linux系统(因为程序员大佬都是用的linux) 虚拟机:vmware  或者virtualbox(官网下载) linux:Ubuntu 使用双系统也可以 虚拟化技术: 1.虚拟机  (全套的系 ...

  10. c语言l博客作业03

    问题 答案 这个作业属于哪个课程 c语言程序设计ll 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/SE2019-3/homework/8727 我在这 ...