目录

概述

案例数据准备

1. 常用操作

2. 中间操作

filter

map

distinct

sorted

limit

skip

flatMap

3. 终结操作

foreach

count

max & min

collect

anyMatch

allMatch

noneMatch

findAny

findFirst

注意事项

(以下学习资料来自b站up主 三更草堂)

概述

Java8 的 Stream 使用的是函数式编程模式,如同它的名字一样,它可以被用来对集合或数组进行链状流式的操作。可以更方便的让我们对集合或数组操作。

案例数据准备

引入依赖

    <dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></dependency></dependencies>

Author实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode//用于后期的去重使用
public class Author {//idprivate Long id;//姓名private String name;//年龄private Integer age;//简介private String intro;//作品private List<Book> books;
}

Book实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode//用于后期的去重使用
public class Book {//idprivate Long id;//书名private String name;//分类private String category;//评分private Integer score;//简介private String intro;}

插入数据

 private static List<Author> getAuthors() {//数据初始化Author author = new Author(1L,"蒙多",33,"一个从菜刀中明悟哲理的祖安人",null);Author author2 = new Author(2L,"亚拉索",15,"狂风也追逐不上他的思考速度",null);Author author3 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);Author author4 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);//书籍列表List<Book> books1 = new ArrayList<>();List<Book> books2 = new ArrayList<>();List<Book> books3 = new ArrayList<>();books1.add(new Book(1L,"刀的两侧是光明与黑暗","哲学,爱情",88,"用一把刀划分了爱恨"));books1.add(new Book(2L,"一个人不能死在同一把刀下","个人成长,爱情",99,"讲述如何从失败中明悟真理"));books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));books2.add(new Book(4L,"吹或不吹","爱情,个人传记",56,"一个哲学家的恋爱观注定很难把他所在的时代理解"));books3.add(new Book(5L,"你的剑就是我的剑","爱情",56,"无法想象一个武者能对他的伴侣这么的宽容"));books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));author.setBooks(books1);author2.setBooks(books2);author3.setBooks(books3);author4.setBooks(books3);List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4));return authorList;}

需求一:

我们可以调用getAuthors方法获取到作家的集合。现在需要打印所有年龄小于18的作家的名字,并且要注意去重。

List<Author> authors = getAuthors();//System.out.println(authors);authors.stream() //把集合转换成流.distinct() //去重.filter(new Predicate<Author>() {  //进行过滤 根据条件@Overridepublic boolean test(Author author) {return author.getAge() < 18;}}).forEach(new Consumer<Author>() {   //打印出来@Overridepublic void accept(Author author) {System.out.println(author.getName());}});}

将匿名内部类转换为lambda表达式:

        List<Author> authors = getAuthors();//System.out.println(authors);//打印出来//进行过滤 根据条件authors.stream() //把集合转换成流.distinct() //去重.filter(author -> author.getAge() < 18).forEach(author -> System.out.println(author.getName()));}

输出结果:

Connected to the target VM, address: '127.0.0.1:50848', transport: 'socket'
亚拉索
易

进入debug模式查看,查看去重,过滤后的结果:

1. 常用操作

目录

概述

案例数据准备

单列集合:集合对象.stream()

        List<Author> authors = getAuthors();Stream<Author> stream = authors.stream();

数组:Arrays.strean()

        Integer[] arr = {1,2,3,4,5};Stream<Integer> stream = Arrays.stream(arr); //传入一个数组,返回一个流对象stream.distinct().forEach(integer -> System.out.println("数字="+integer));
        Integer[] arr = {1,2,3,4,5};//Stream<Integer> stream = Arrays.stream(arr); //传入一个数组,返回一个流对象Stream<Integer> arr1 = Stream.of(arr); //也可以用这种方式将数组转换为stream流arr1.distinct().forEach(integer -> System.out.println("数字="+integer));

双列集合:转换为单列集合后再创建 (Map)

        Map<String,Integer> map = new HashMap<>();map.put("蜡笔小新",19);map.put("黑子",17);map.put("日向翔阳",16);//将map转换为单列集合 SetSet<Map.Entry<String, Integer>> entrySet = map.entrySet();Stream<Map.Entry<String, Integer>> stream = entrySet.stream();stream.filter(entry -> entry.getValue() > 16).forEach(stringIntegerEntry -> System.out.println(stringIntegerEntry.getKey()+"="+stringIntegerEntry.getValue()));

2. 中间操作

filter

需求:打印所有姓名长度大于1的作家的姓名

        List<Author> authors = getAuthors();authors.stream().filter(author -> author.getName().length() > 1).forEach(author -> System.out.println(author.getName()));

 map

可以把流当中的元素进行计算或转换

需求:打印所有作家的姓名

方式一:直接用foreach打印

        List<Author>authors = getAuthors();authors.stream().forEach(author -> System.out.println(author.getName()));

方式二:将流当中的Author类型转换为String类型输出

Function方法中第一个泛型的类型必须和流当中的类型一致

        List<Author>authors = getAuthors();//把流当中的元素进行类型转换 第一个参数一般不变,第二个参数是要把流当中的元素转换成什么,比如只是姓名(String)authors.stream().map(new Function<Author, String>() {@Override//参数是第一个定义的类型 Author ,方法返回值是 Stringpublic String apply(Author author) {return author.getName();}}).forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});

转换为lambda

        authors.stream().map(author -> author.getName()).forEach(s -> System.out.println(s));

 distinct

去除流中重复的元素

依赖的是Object.equals()方法来判断是否是重复的对象。所以注意需要重写equals方法。

需求:打印所有作家的姓名,并且要求其中不能有重复元素。

        List<Author> authors = getAuthors();authors.stream().distinct().forEach(author -> System.out.println(author.getName()));

 sorted

需求:对流当中的元素进行排序,按照年龄来排序,降序,要求不能有重复元素

注意:如果调用空参的sorted()方法,需要流中的元素是实现了Comparable接口的。

public class Author implements Comparable<Author>{private Long id;private String name;private Integer age;private String intro;private List<Book> books;@Overridepublic int compareTo(Author o) {return o.getAge()- this.getAge() ;}
}
        List<Author> authors = getAuthors();authors.stream().distinct().sorted().forEach(author -> System.out.println(author.getAge()));

使用sort的有参的方法

        List<Author> authors = getAuthors();authors.stream().distinct().sorted(new Comparator<Author>() {@Overridepublic int compare(Author o1, Author o2) {return o2.getAge()- o1.getAge();}}).forEach(author -> System.out.println(author.getAge()));}

limit

可以设置流的最大长度,超出的部分将被抛弃

需求:对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素,然后打印其中年龄最大的两个作家的姓名。

        List<Author> authors = getAuthors();authors.stream().distinct().sorted().limit(2).forEach(author -> System.out.println(author.getName()));

skip

跳过流中的前n个元素,返回剩下的元素

需求:打印除了年龄最大的作家外的其他作家,要求不能有重复元素,并且按照年龄降序排序。

        List<Author> authors = getAuthors();authors.stream().distinct().sorted().skip(1) //跳过第一个元素 从1 开始.forEach(author -> System.out.println(author.getName()));}

flatMap

map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素。

需求一:打印所有书籍的名字。要求对重复的元素进行去重。

如果直接getBooks() ,拿到的都是book的list集合,而不是book对象

        authors.stream().map(author -> author.getBooks()).forEach(new Consumer<List<Book>>() {@Overridepublic void accept(List<Book> books) {System.out.println(books);}});

如果希望流当中的元素都变成book对象,需要用flatMap

要求返回的类型是 Stream流对象

        authors.stream().flatMap(new Function<Author, Stream<Book>>() {@Overridepublic Stream<Book> apply(Author author) {return author.getBooks().stream(); //先获取集合,再将集合转换为流对象}}).distinct().forEach(new Consumer<Book>() {@Overridepublic void accept(Book book) {System.out.println(book.getName());}});

需求二: 打印现有数据的所有分类。要求对分类进行去重。不能出现这种格式:哲学,爱情

        List<Author> authors = getAuthors();authors.stream().flatMap((Function<Author, Stream<Book>>) author -> author.getBooks().stream()).distinct().flatMap(book -> Arrays.stream(book.getCategory().split(",")))//将目录按照,分割,然后放到数组里,再转换成stream流,里面元素都是String类型.distinct() //对分类进行去重.forEach(category -> System.out.println(category));

3. 终结操作

foreach

对流当中的元素进行遍历操作,我们通过传入的参数去指定对遍历的元素进行什么具体的操作。

        authors.stream().map(author -> author.getName()).distinct().forEach(name -> System.out.println(name));}

 count

用来获取当前流中元素的个数。

需求:打印这些作家的所出书籍的数目,注意删除重复元素。

    private static void test13() {//要让流中的元素是书List<Author> authors = getAuthors();long count = authors.stream().flatMap(author -> author.getBooks().stream()).distinct().count();System.out.println(count);}

max & min

取流中的最值

需求:分别获取这些作家的所出书籍的最高分和最低分并打印。

        List<Author> authors = getAuthors();Optional<Integer> max = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore()).max((score1, score2) -> score1 - score2);Optional<Integer> min = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore()).min(new Comparator<Integer>() {@Overridepublic int compare(Integer score1, Integer score2) {return score1 - score2;}});System.out.println(max.get());System.out.println(min.get());

collect

把当前流转换为一个集合

需求一:获取一个存放所有作者名字的 List 集合

    private static void test15() {List<Author> authors = getAuthors();List<String> nameList= authors.stream().map(author -> author.getName()).collect(Collectors.toList());System.out.println(nameList);}
[蒙多, 亚拉索, 易, 易]

需求二:获取一个存放所有作者名字的 Set集合

    private static void test16() {List<Author> authors = getAuthors();Set<String> nameSet = authors.stream().map(author -> author.getName()).collect(Collectors.toSet());System.out.println(nameSet);}
[亚拉索, 蒙多, 易]

需求三:获取一个map集合,map的key为作者名,value为List<Book>

        List<Author> authors = getAuthors();Map<String, List<Book>> map = authors.stream().distinct().collect(Collectors.toMap(new Function<Author, String>() {@Overridepublic String apply(Author author) {return author.getName();}}, new Function<Author, List<Book>>() {@Overridepublic List<Book> apply(Author author) {return author.getBooks();}}));System.out.println(map);

 查找和匹配

 anyMatch

可以用来判断是否有任意符合匹配条件的元素,结果为boolean类型。

需求:判断是否有年龄在29以上的作家

        List<Author> authors = getAuthors();boolean b = authors.stream().anyMatch(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge() > 29;}});System.out.println(b);

 allMatch

可以用来判断是否都符合匹配条件,结果为boolean类型。如果都符合结果为true,否则结果为false。

需求:判断是否所有的作家都是成年人

        List<Author> authors = getAuthors();boolean b = authors.stream().allMatch(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge() >= 18;}});System.out.println(b);

noneMatch

可以判断流中的元素是否都不符合匹配条件。如果都不符合结果为true,否则结果为false

findAny

获取流中的任意一个元素。该方法没有办法保证获取的一定是流中的第一个元素。

需求:获取任意一个年龄大于18的作家,如果存在就输出他的名字  返回的对象是Optional<Author>

    private static void test20() {List<Author> authors = getAuthors();Optional<Author> any = authors.stream().filter(author -> author.getAge() > 18).findAny();any.ifPresent(new Consumer<Author>() {@Overridepublic void accept(Author author) {System.out.println(author.getName());}});}
蒙多

findFirst

获取流中的第一个元素。

需求:获取一个年龄最小的作家,并输出他的姓名。

先按sorted排序,按年龄从小到大,然后获取第一个。

    private static void test21() {List<Author> authors = getAuthors();Optional<Author> first = authors.stream().sorted(new Comparator<Author>() {@Overridepublic int compare(Author o1, Author o2) {return o1.getAge() - o2.getAge();}}).findFirst();first.ifPresent(new Consumer<Author>() {@Overridepublic void accept(Author author) {System.out.println(author.getName() + author.getAge());}});}
易14

改成 o2 -o1 获取的就是第一个年龄最大的

对流中的数据按照你指定的计算方式计算出一个结果。 (缩减操作)

reduce的作用是把stream中的元素给组合起来,我们可以传入一个初始值,它会按照我们的计算方式依次拿流中的元素和初始化值进行计算,计算结果再和后面的元素计算。

reduce两个参数的重载形式内部的计算方式如下:

其中identity就是我们可以通过方法参数传入的初始值,accumulator的apply具体进行什么计算也是我们通过方法参数来确定的。

T result = identity;
for (T element : this stream)result = accumulator.apply(result, element)
return result;

需求一:使用reduce求所有作者年龄的和

    private static void test22() {List<Author> authors = getAuthors();Integer sum = authors.stream().map(author -> author.getAge()).reduce(0, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer result, Integer element) {return result + element;}});System.out.println(sum);}

需求二: 使用reduce求所有作者中年龄的最大值

先将Author 流 转换为Integer类型的流 然后使用reduce 找到最大年龄

    private static void test23() {List<Author> authors = getAuthors();Integer reduce = authors.stream().map(author -> author.getAge()).reduce(Integer.MIN_VALUE, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer result, Integer element) {return element > result ?  element : result;}});System.out.println(reduce);}

需求三:使用reduce求所有作者中年龄的最小值

    private static void test24() {List<Author> authors = getAuthors();Integer reduce = authors.stream().map(author -> author.getAge()).reduce(Integer.MAX_VALUE, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer result, Integer element) {return result > element ? element : result;}});System.out.println(reduce);}

一个参数的重载形式内部的计算:

      boolean foundAny = false;T result = null;for (T element : this stream) {if (!foundAny) {foundAny = true;result = element;}elseresult = accumulator.apply(result, element);}return foundAny ? Optional.of(result) : Optional.empty();

注意事项

  • 惰性求值              如果没有终结操作,中间的操作是不会被执行的
  • 流是一次性的       一个流对象经过一次终结操作以后,就不能再被使用
  • 不会影响原数据   我们再流中可以对数据做很多处理,但是正常情况下是不会影响原来集合中的元素的。

Java函数式编程学习——Stream流相关推荐

  1. JUC源码级学习(下)-函数式编程、stream流、jvm等

    12.四大函数式接口(必需掌握) 新时代的程序员:lambda表达式.链式编程.函数式接口.Stream流式计算 函数式接口: 只有一个方法的接口 @FunctionalInterface publi ...

  2. Java8函数式编程、Stream流、Option的使用,一篇足够了

    为什么要学 大数量下处理集合效率高 代码可读性高 消灭嵌套地狱 // 查询未成年作家的评分在70以上的书籍 List<Book> bookList = new ArrayList<& ...

  3. 【深入理解函数式编程】stream流式提取字符串中数字

    问题 字符串处理是日常开发中接触最频繁的一种,如何从字符串中提取符合特定条件的信息则是更为频繁.本文介绍一种利用stream方式来提取字符串中数字的方法,供学习借鉴和参考,以便今后能够加以应用. 方法 ...

  4. Java函数式编程学习——Optional

    概述 我们在编写代码的时候出现最多的就是空指针异常.所以在很多情况下我们需要做各种非空的判断. 模拟一个空指针异常: public class OptionalDemo {public static ...

  5. 【Java】函数式编程学习笔记——Stream流

    学习视频:https://www.bilibili.com/video/BV1Gh41187uR?p=1 (1)[Java]函数式编程学习笔记--Lambda表达式 (2)[Java]函数式编程学习笔 ...

  6. Java 8 函数式编程学习笔记

    Java 8 函数式编程学习笔记 @(JAVASE)[java8, 函数式编程, lambda] Java 8 函数式编程学习笔记 参考内容 Java 8中重要的函数接口 扩展函数接口 常用的流操作 ...

  7. 【Java】Java函数式编程以及流的操作

    文章目录 大纲 lambda表达式 一般内部类 局部内部类 匿名内部类 基于函数式接口的lambda表达式 JDK8中自带的函数式接口 Predicate判断 Consumer消费 Supplier供 ...

  8. Java函数式编程 - 再谈Stream

    Java函数式编程 - 再谈Stream 1.reduce() 前一章节说了Stream一些使用方式,Stream.reduce()也是Stream中的一个终结操作.使用起来较为复杂一些 1.1 概念 ...

  9. java函数式编程归约reduce概念原理 stream reduce方法详解 reduce三个参数的reduce方法如何使用

    java函数式编程归约reduce概念原理 stream reduce方法详解 reduce三个参数的reduce方法如何使用

最新文章

  1. apkplug插件托管服务简化与简介-05
  2. ajax提交后立刻刷新,Ajax提交表单页面刷新很快的解决方法
  3. 深入探究VC —— 编译器cl.exe(1)
  4. pt939g联通_尝试修改友华PT939G的省份设置,成功!
  5. FlashDevelop 遇到的Process not responding 问题
  6. Echarts常用配置参数
  7. 为什么越来越多的企业选择云数据存储而放弃本地数据存储?
  8. 在普通用户下进入root用户
  9. 漫漫的webim(一) web实现简易im功能
  10. 机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析...
  11. 常见软包电池厚度尺寸测量方法对比
  12. mysql大写和小写_MySQL大写和小写问题
  13. vue学习笔记(一) ---- vue指令(过滤器)
  14. Bank相关1_数据移行
  15. C++:求整数num中包含因子k的个数
  16. webgl_浏览器支持问题
  17. 使用apache服务部署静态网站--初篇
  18. Arduino与Proteus仿真实例-温控风扇仿真
  19. 【一句话博客】SyntaxError: Failed to execute ‘querySelector’ on ‘Document’: “xxx” is not a valid selector.
  20. 基于Java开发一套完整的区块链系统

热门文章

  1. “数据折叠”:今天,那些人工智能背后“标数据的人”正在回家
  2. http转义与url编码
  3. 推荐几款渗透测试常用的脚本(记得收藏)
  4. 地名能否作为商标使用
  5. 牛客 郊区春游 状压+最短路
  6. JProfiler让人痛彻心扉的安装与部署
  7. Airtest入门案例-操作网易云音乐
  8. 如何理解类与对象、继承
  9. 钱宝网可靠吗? 不信可以先试用后在说
  10. 计算机视觉中的MAP的理解(mean average precision)