Java——Stream流的学习

这篇具有很好参考价值的文章主要介绍了Java——Stream流的学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在开发过程中,经常或忽略流的使用,导致用的不熟练,于是抽时间系统的学习下stream的使用,找了哔哩哔哩的教程跟着看看练练。

准备工作

创建Book、Aurhor实体类,初始化数据

public static List<Author> getAuthors() {
        Author author1 = 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, "吹或不吹", "爱情,个人传记", 65, "一个哲学家的恋爱观注定很难"));

        books3.add(new Book(5L, "你的剑就是我的剑", "爱情", 56, "无法想象一个武者"));
        books3.add(new Book(5L, "风与剑", "个人传记", 100, "两个哲学家灵魂与肉体的碰撞"));
        books3.add(new Book(5L, "风与剑", "个人传记", 100, "两个哲学家灵魂与肉体的碰撞"));

        author1.setBooks(books1);
        author2.setBooks(books2);
        author3.setBooks(books3);
        author4.setBooks(books3);

        List<Author> authors = new ArrayList<>(Arrays.asList(author1, author2, author3, author4));
        return authors;
    }

创建流

// 1.单列集合
private static void test01(List<Author> authors) {
	authors.stream().distinct().filter(author -> author.getAge()<18).forEach(author -> System.out.println(author.getName()));
}
// 2.数组流
private static void test02() {
    Integer[] arr = {1,2,3,4,5};
//  IntStream stream = Arrays.stream(arr);
    Stream<Integer> stream = Stream.of(arr);
    stream.distinct().filter(value -> value > 2).forEach(value -> System.out.println(value));
}
// 3.双列集合   map流
private static void test03() {
    Map<String, Integer> map = new HashMap<>();
    map.put("张三", 18);
    map.put("李四", 33);
    map.put("王五", 25);

    Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();
    stream.filter(entry -> entry.getValue()>20).forEach(entry -> System.out.println(entry.getKey()));
}

中间操作

  • filter 对流中的操作进行过滤,符合条件的返回
    使用的函数式接口是:Predicate,参数是一个实体,拥有抽象方法:boolean test(T t);
authors.stream().filter(new Predicate<Author>() {
    @Override
    // 匿名内部类的test方法,将传入的author进行判断,返回符合条件的
    public boolean test(Author author) {
        return author.getName().length() > 1;
    }
}).forEach(author -> System.out.println(author.getName()));

该操作将作者名字长度>1 的作者名列出来

  • map 把流中元素进行计算或转换
    使用的函数式接口是:Function<T, R>,参数是一个实体,和一个要将实体转化的结果result,拥有抽象方法:R apply(T t);
    (1)进行转换,该操作将作者名字列出来
private static void test05(List<Author> authors) {
    authors.stream().map(new Function<Author, String>() {
        @Override
        // 匿名内部类的apply方法,将传入的author进行需要的结果返回
        public String apply(Author author) {
            return author.getName();
        }
   }).forEach(s -> System.out.println(s));
}

(2)进行计算,该操作将作者年龄分别+10

authors.stream().map(author -> author.getAge())
                .map(new Function<Integer, Integer>() {
                    @Override
                    public Integer apply(Integer age) {
                        return age + 10;
                    }
                })
                .forEach(s -> System.out.println(s));

第一个map是获取作者的年龄,然后第二个map则将年龄转换为年龄,只是经过了+10计算,我们打断点看看
Java——Stream流的学习,【Java】,java
流经过第一个map后转换为了Integer
Java——Stream流的学习,【Java】,java
经过第二个map后将第一个Integer进行+10计算,类型不变

  • distinct 将元素进行去重操作
    注意:distinct 依赖Object 的equals方法来判断对象是否相同,对象要重写equals方法。
authors.stream().distinct().forEach(author -> { System.out.println(author.getName()); });

该操作直接通过distinct去重
当然也可以使用前面的map提取出名字,再去重,比上面的麻烦些

authors.stream().distinct().map(new Function<Author, String>() {
            @Override
            public String apply(Author author) {
                return author.getName();
            }
        }).forEach(name -> { System.out.println(name); });

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

该操作先使用map将Author对象转换为姓名的String,然后在去重

  • flatMap
    上面的Map是把一个对象转换成另一个对象作为流中的元素,而flatMap是把一个对象转换为多个对象作为流中的元素

使用的函数式接口是:new Function<T, R>,将一个对象转换成Stream对象

(1)打印所有书籍的名字,要求对重复的元素进行去重。

authors.stream()
	   .flatMap(new Function<Author, Stream<Book>>() {
	        // 这里可以通过idea进行lambda转换,为了清晰就不转了
            @Override
            public Stream<Book> apply(Author author) {
                return author.getBooks().stream();
            }
           })
        .distinct()
        .forEach(name -> { System.out.println(name); });

如果使用Map,将作者对象提取出书籍对象,还需要再对书籍对象List进行遍历去重,比较麻烦。
首先使用flatMap将每个作者对象中的书籍对象流提取出来,然后直接在书籍对象流中进行去重,输出书籍名称。
Java——Stream流的学习,【Java】,java
Java——Stream流的学习,【Java】,java
(2)打印现有数据的所有分类,要求对分类进行去重,不能出现这种格式:哲学,爱情,需要转成两个分类

authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                // 将分类进行分割成数组后,转成流进行去重
                .flatMap(book -> Arrays.stream(book.getCategory().split(",")))
                .distinct()
                .forEach(category -> System.out.println(category));

Java——Stream流的学习,【Java】,java
第一次使用flatmap将作者对象转换成多个书籍对象流
Java——Stream流的学习,【Java】,java

第二次使用flatmap将书籍对象的分类转换成多个分类流

终结操作

  • forEach 对流中元素进行遍历操作
  • count 获取当前流中元素的个数
    (1)打印这些作家所出书籍的数目,注意删除重复元素
    因为count属于终结操作,会有返回值
long count = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .count();
System.out.println("书籍count = " + count);

Java——Stream流的学习,【Java】,java
使用flatMap获取每个书籍对象,去重计算
Java——Stream流的学习,【Java】,java

  • min和max 求流中的最值
    (1)获取这些作家的所出书籍的最高分和最低分
Optional<Integer> max = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .map(book -> book.getScore())
                .max(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer score1, Integer score2) {
                        return score1 - score2;
                    }
                });
System.out.println("书籍评分max = " + max.get());

Optional<Integer> min = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .map(book -> book.getScore())
                .min(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer score1, Integer score2) {
                        return score1 - score2;
                    }
                });
System.out.println("书籍评分min = " + min .get());

先使用flatMap将作者对象转换成多个书籍对象流,然后用map获取书籍对象中的评分对象,进行max和min计算

  • collect 把当前流转换成一个集合
    (1)获取一个存放所有作者名字的List集合
List<String> list = authors.stream()
                .map(author -> author.getName())
                .distinct()
                .collect(Collectors.toList());

System.out.println("list = " + list);

(2)获取一个所有书名的set集合

Set<String> set = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .map(book -> book.getName())
                .collect(Collectors.toSet());

System.out.println("set = " + set);

(3)获取一个map集合,key为作者名,value为List

Map<String, List<Book>> map = authors.stream()
                // 去重避免key重复
                .distinct()
                .collect(Collectors.toMap(new Function<Author, String>() {
                    @Override 
                    // 这里的匿名内部类将传入作者对象,获取作者名作为key
                    public String apply(Author author) { 
                        return author.getName(); 
                    }
                    }, new Function<Author, List<Book>>() {
                    @Override 
                    // 这里的匿名内部类将传入作者对象,获取书籍list作为value
                    public List<Book> apply(Author author) { 
                        return author.getBooks(); 
                    }
                }));

System.out.println("map = " + map);

简化lambda表达式

Map<String, List<Book>> map = authors.stream()
                // 去重避免key重复
                .distinct()
                .collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));

System.out.println("map = " + map);
  • anyMatch 判断流中是否有任意符合匹配条件的元素,符合返回true
boolean b = authors.stream().anyMatch(author -> author.getAge() > 29);

System.out.println("b = " + b);

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

  • allMatch 判断流中元素是否都符合条件,都符合为true,否则为false
boolean b = authors.stream().allMatch(author -> author.getAge() >= 18);
System.out.println("b = " + b);

判断是否所有作家都是成年人

  • noneMatch 判断流中元素是否都不符合条件,是为true,否为false
boolean b = authors.stream().noneMatch(author -> author.getAge() > 100);
System.out.println("b = " + b);

判断作家是否都没有超过100岁的

  • findAny 获取流中符合条件的任意一个元素,不保证为流中的第一个元素
Optional<Author> au = authors.stream().filter(author -> author.getAge() > 18).findAny();

System.out.println("名字:" + au.get().getName());

这里用的get方法获取数据,但是可能出现找不到符合条件的数据,这时候get就会报错,如:
Java——Stream流的学习,【Java】,java
所以改成:

Optional<Author> au = authors.stream().filter(author -> author.getAge() > 98).findAny();

au.ifPresent(author -> System.out.println(author.getName()));

获取任意一个大于18的作家,输出名字

  • findFirst 获取流中的第一个元素
Optional<Author> author = authors.stream()
                .sorted((o1, o2) -> o1.getAge() - o2.getAge())
                .findFirst();

author.ifPresent(author1 -> System.out.println(author1.getName()));

获取年龄最小的作家,输出名字

  • reduce归并 对流中的数据按照指定的计算方式计算出一个结果(缩减操作)
    把stream中的元素组合起来,传入初始化值,按照指定的计算方式和元素进行计算,计算结果再和下一个元素进行计算,依次计算完

reduce有三种重载方式

  1. 2个参数的
    T reduce(T identity, BinaryOperator accumulator);
T result = identity;
for (T element : this stream) {
	result = accumulator.apply(result, element)
}
return result;

传入初始化值作为第一个参数identity,传入计算方法accumulator.apply 进行初始化值和元素的计算

例子:
(1)使用reduce对作者年龄进行求和

Integer result = authors.stream()
                .distinct()
                .map(author -> author.getAge())
                // 传入初识值和计算方法
                .reduce(0, new BinaryOperator<Integer>() {
                    @Override
                    public Integer apply(Integer result, Integer element) {
                        return result + element;
                    }
                });

System.out.println("result = " + result);

lambda写

Integer result = authors.stream()
                .distinct()
                .map(author -> author.getAge())
                // 传入初识值和计算方法
                .reduce(0, (result1, element) -> result1 + element);

System.out.println("result = " + result);

(2)使用reduce求所有作者年龄最大值

Integer max = authors.stream()
                .distinct()
                .map(author -> author.getAge())
                .reduce(Integer.MIN_VALUE, new BinaryOperator<Integer>() {
                    @Override
                    public Integer apply(Integer result, Integer element) {
                        return result > element ? result : element;
                    }
                });
System.out.println("max = " + max);

(3)使用reduce求所有作者年龄最小值

Integer min = authors.stream()
                .distinct()
                .map(author -> author.getAge())
                .reduce(Integer.MAX_VALUE, new BinaryOperator<Integer>() {
                    @Override
                    public Integer apply(Integer result, Integer element) {
                        return result > element ? element : result;
                    }
                });

System.out.println("min = " + min);
  1. 1个参数的
    Optional reduce(BinaryOperator accumulator);
boolean foundAny = false;
T result = null;
for (T element : this stream) {
	if (!foundAny) {
		foundAny = true;
		result = element;
	} else {
		result = accumulator.apply(result, element);
	}
}

return foundAny ? Optional.of(result) : Optional.empty();

该方法只传入了一个计算方式,根据实现方法,可以看到将流中的第一个元素作为了第一个元素result,然后后续进行else内部的计算

例如:文章来源地址https://www.toymoban.com/news/detail-831165.html

Optional<Integer> optional = authors.stream()
                .distinct()
                .map(author -> author.getAge())
                // 直接传入计算方法
                .reduce((result, element) -> result > element ? element : result);

optional.ifPresent(integer -> System.out.println(integer));

到了这里,关于Java——Stream流的学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java,SpringBoot中对Stream流的运用

    详细参考:java 1.8 stream 应用-22种案例_java1.8 流案例-CSDN博客 1. 遍历  2. 汇总

    2024年02月22日
    浏览(36)
  • 带你走进Java8新特性Stream流的小世界

    目录 一. 什么是流(Stream) 1.1 流的定义 1.2 流的特点 1.3 操作流 1.4 创建流 二. 流的中间操作 2.1 流的筛选与切片 2.1.1 filter 2.1.2 limit 2.1.3 skip 2.1.4 distinct 2.2 流的映射 2.2.1 map 2.2.2 flatMap 2.3 流的排序 2.3.1 sort 三. 流的终止操作 3.1 流的查找与匹配 3.1.1 allMatch 3.1.2 anyMatch 3.1.3 none

    2024年01月24日
    浏览(50)
  • Java8特性,Stream流的使用,收集成为map集合

    Java 8引入了Stream API,这是Java集合操作的一个重大改进。Stream API提供了一种高效且易于使用的处理数据的方式。 Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。注意:Stream自己不会存储元素,它不会改变源对象,反而它的操作会返回一个全新的Strea

    2024年04月22日
    浏览(63)
  • java 8 stream流的19种用法,可应对大多数集合的处理场景

    java 8的Stream API是一种非常强大的集合处理工具,它提供了一种新的、高效的、声明式的方式来处理集合数据。下面我们就来看一下Java 8 Stream API的所有用法。 可以使用Stream.of()方法创建一个Stream: 也可以使用集合的stream()方法创建一个Stream: 可以使用filter()方法过滤Stream中的

    2023年04月08日
    浏览(65)
  • java通过stream流的形式把列表中某个字段的值取出并生成列表

    可以使用Java 8中引入的Stream API来实现这一功能。例如,假设你有一个类名为Person的列表,并且你想要从这个列表中提取所有人的姓名并生成一个新的列表。你可以这样做: 这段代码首先使用 stream() 方法将列表转换为流。然后,使用 map() 方法对流中的每个元素执行一个转换函

    2024年02月12日
    浏览(30)
  • 深度解析Java JDK 1.8中Stream流的源码实现:带你探寻数据流的奥秘

    1.1 什么是Stream流,以及它的主要特点和优势 什么是Stream流 ? jdk1.8 中引入的Stream流是一种用 函数式编程方式 操作集合的新特性,提供了一种更简洁、高效的方式来处理集合数据,可以将集合操作转换为一系列的流水线操作,实现更加优雅和功能强大的数据处理。 主要特点

    2024年03月16日
    浏览(49)
  • 由于对象流解析的数据与流的头部信息不匹配导致异常 java.io.StreamCorruptedException: invalid stream header: 7372001

    错误原因 先直接说错误原因 当使用对象流时,对象头和对象内容一起被写入输出流,而读取时也需要以相同的顺序读取对象头和对象内容 如果读取时的顺序与写入时的顺序不一致,或者在写入或读取对象头和对象内容之间更改了流的状态,则会出现 java.io.StreamCorruptedExcept

    2024年02月05日
    浏览(38)
  • 学习Java 8 Stream,提升编码能力!

    Java 11中提供了一组强大的Stream API,使得我们可以更加方便地对集合进行过滤、排序、映射等操作。本文将介绍Java 11 Stream API的使用,包括创建Stream、中间操作、终止操作等内容。 在Java 11中,可以通过多种方式创建Stream对象,包括从集合、数组、文件等数据源创建Stream。 可

    2024年02月13日
    浏览(47)
  • Java 8:Stream API 流式操作(学习)

    Java 8 中的 Stream API 是一组用于对集合数据进行处理的新特性;提供一种以声明式风格对集合进行操作的方式,简化集合的处理,使得代码更加简洁、优雅,并且能够更高效地处理数据; 这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进

    2024年02月10日
    浏览(34)
  • 【从零开始学习JAVA | 第二十九篇】Stream流

    目录 前言: Stram流: 设计目标: 使用步骤: 1.先得到一条Stream流,并把数据放上去。 2.利用Stream流中的各种API进行操作。 使用Stream流的注意事项: 总结:         本文我们将学习Stream流,他就像流水线一样,可以对我们要处理的对象进行逐步处理,最终达到我们想要的效果

    2024年02月17日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包