JDK8 新特性 Stream API 进阶 (结合案例详解--通透--讲清)

这篇具有很好参考价值的文章主要介绍了JDK8 新特性 Stream API 进阶 (结合案例详解--通透--讲清)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

👳我亲爱的各位大佬们好😘😘😘
♨️本篇文章记录的为 JDK8 新特性 Stream API 进阶 相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉🙉。
♨️如果文章有什么需要改进的地方还请大佬不吝赐教❤️🧡💛
👨‍🔧 个人主页 : 阿千弟
🔥 相关内容👉👉👉 : 都2023年了,如果不会Lambda表达式、函数式编程?你确定能看懂公司代码?

前情回顾 :

最近, 我的一些已经入职一段时间的朋友和我说, 在公司中做的最多的业务就是crud, 他最近做的项目是一个h5的中移动一个外包项目, 虽然业务并不复杂, 但是呢数据量非常庞大, 数据库的表很多, 大概四五百张表, 每天的crud写的我这哥们也是很烦.😭😭😭

所以对于这个问题, 建议哥们可以尝试使用 JDK8 新特性 Stream的方式来处理数据, 对于集合, 数组, map的处理很方便, 也很快速, 这时一些朋友会问, stream阅读性不好, 难以读懂, 但是呢你想想别管它咋样, 能有利于咱们开发提高咱们的开发效率就行了呗

为此我专门出来一期关于JDK8 新特性 Stream API 进阶使用的文章, 来帮助咱们经常写crud的朋友来简化开发, 可能你刚开始用的时候很抵触, 但是你用熟练了会觉得它真的爽.🙏🙏🙏希望大家多多支持

JDK8 新特性 Stream API 进阶 (结合案例详解--通透--讲清)

1、了解 Stream

​ Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是Stream API(java.util.stream.*)。Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

2、什么是 Stream

流(Stream) 到底是什么呢?

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,流讲的是计算!”

注意:

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  • Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

3、Stream 的操作三个步骤

  • 创建 Stream

一个数据源(如:集合、数组),获取一个流

  • 中间操作

一个中间操作链,对数据源的数据进行处理

  • 终止操作(终端操作)

一个终止操作,执行中间操作链,并产生结果

Stream 的中间操作

​ 多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

1、筛选与切片

方 法 描 述
filter(Predicate p) 接收 Lambda , 从流中排除某些元素。
distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
limit(long maxSize) 截断流,使其元素不超过给定数量。
skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补

2、映射

方 法 描 述
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。
mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。
mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。
flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

3、排序

方 法 描 述
sorted() 产生一个新流,其中按自然顺序排序
sorted(Comparator comp) 产生一个新流,其中按比较器顺序排序

Stream 的终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void。

1、查找与匹配

方 法 描 述
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意元素
count() 返回流中元素总数
max(Comparator c) 返回流中最大值
min(Comparator c) 返回流中最小值
forEach(Consumer c) 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了)

2、归约

方 法 描 述
reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 T
reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 Optional

3、收集

方 法 描 述
collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

​ Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:

方法 返回类型 作用 代码
toList List 把流中元素收集到List List emps= list.stream().collect(Collectors.toList());
toSet Set 把流中元素收集到Set Set emps= list.stream().collect(Collectors.toSet());
toCollection Collection 把流中元素收集到创建的集合 Collectionemps=list.stream().collect(Collectors.toCollection(ArrayList::new));
counting Long 计算流中元素的个数 long count = list.stream().collect(Collectors.counting());
summingInt Integer 对流中元素的整数属性求和 int total=list.stream().collect(Collectors.summingInt(Employee::getSalary));
averagingInt Double 计算流中元素Integer属性的平均值 double avg= list.stream().collect(Collectors.averagingInt(Employee::getSalary));
summarizingInt IntSummaryStatistics 收集流中Integer属性的和。 IntSummaryStatisticsiss= list.stream().collect(Collectors.summarizingInt(Employee::getSalary));
joining String 连接流中每个字符串 String str= list.stream().map(Employee::getName).collect(Collectors.joining());
maxBy Optional 根据比较器选择最大值 Optionalmax= list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
minBy Optional 根据比较器选择最小值 Optional min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));
reducing 归约产生的类型 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值 int total=list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum));
collectingAndThen 转换函数返回的类型 包裹另一个收集器,对其结果转换函数 int how= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
groupingBy Map<K, List> 根据某属性值对流分组,属性为K,结果为V Map<Emp.Status, List> map= list.stream().collect(Collectors.groupingBy(Employee::getStatus));
partitioningBy Map<Boolean, List> 根据true或false进行分区 Map<Boolean,List>vd= list.stream().collect(Collectors.partitioningBy(Employee::getManage));

JDK8 新特性 Stream API 进阶 (结合案例详解--通透--讲清)

下面是工作中经常被用到的案例, 请仔细品味

一些使用场景

1、取出自身重复的数据

@Test
public void test01() {
    List<String> list = Arrays.asList(
        "g", "k", "f", "k", "g", "b"
    );
    List<String> li = list.stream().
    		filter(li1 -> list.stream().filter((li2 -> li2.equals(li1))).count() > 1l)
        	.collect(toList());
    System.out.println(li);
}

2、累加数字

@Test
public void test12() {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    Integer sum = list.stream()
        .reduce(0, (x, y) -> x + y);
    System.out.println(sum);
}

3、字符串数字集合与整数集合互转

@Test
public void test14() {
    List<Integer> intList = new ArrayList<>();
    intList.add(1);
    intList.add(3);
    intList.add(4);
    List<String> intToStrList = intList.stream().map(String::valueOf).collect(toList());
    intToStrList.stream().forEach(str -> {
        System.out.println(str);
    });

    List<String> stringList = new ArrayList<>();
    stringList.add("10");
    stringList.add("20");
    stringList.add("30");
    List<String> stringToIntList = stringList.stream().map(String::valueOf).collect(toList());
    stringToIntList.stream().forEach(num -> {
        System.out.println(num);
    });
}

4、取list1与list2的交集

List<String> list1 = Arrays.asList(
    "张三", "李四", "李刚", "隋通"
);

List<String> list2 = Arrays.asList(
    "熊大", "熊二", "张三", "李刚"
);

//15.取list1与list2的交集
@Test
public void test15() {
    List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(toList());
    System.out.println("---得到交集---");
    intersection.parallelStream().forEach(System.out::println);
}

5、取list1与list2的差集

@Test
public void test16() {
    List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(toList());
    System.out.println("---得到差集 reduce1 (list1 - list2)---");
    reduce1.parallelStream().forEach(System.out::println);
}

6、取list1和list2的并集

@Test
public void test18() {
    List<String> listAll = list1.parallelStream().collect(toList());
    List<String> listAll2 = list2.parallelStream().collect(toList());
    listAll.addAll(listAll2);
    System.out.println("---得到并集 listAll---");
    listAll.parallelStream().forEach(System.out::println);
    // 去重并集
    List<String> listAllDistinct = listAll.stream().distinct().collect(toList());
    System.out.println("---得到去重并集 listAllDistinct---");
    listAllDistinct.parallelStream().forEach(System.out::println);
    System.out.println("---原来的List1---");
    list1.parallelStream().forEach(System.out::println);
    System.out.println("---原来的List2---");
    list2.parallelStream().forEach(System.out::println);
}

7、统计集合重复元素出现次数,并且去重返回hashmap

List<String> list = Arrays.asList(
    "b", "g", "d", "d", "t", "j", "d", "a", "c", "f", "a", "b", "s", "w", "w", "b"
);

//19.统计集合重复元素出现次数,并且去重返回hashmap
@Test
public void test19() {
    Map<String, Long> map = list.stream().
        collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    System.out.println(map);
    //由于hashmap无序,所以在排序放入LinkedHashMap里(key升序)
    Map<String, Long> sortMap = new LinkedHashMap<>();
    map.entrySet().stream().sorted(Map.Entry.comparingByKey()).
        forEachOrdered(e -> sortMap.put(e.getKey(), e.getValue()));
    System.out.println(sortMap);
    //获取排序后map的key集合
    List<String> keys = new LinkedList<>();
    sortMap.entrySet().stream().forEachOrdered(e -> keys.add(e.getKey()));
    System.out.println(keys);
    //获取排序后map的value集合
    List<Long> values = new LinkedList<>();
    sortMap.entrySet().stream().forEachOrdered(e -> values.add(e.getValue()));
    System.out.println(values);
}

8、stream循环拿到下标

@Test
public void test21(){
    Stream.iterate(0, i -> i + 1).limit(users01.size()).forEach(index -> {
        System.out.println(index);
    });
}

9、List集合转Map任意一个属性作为键,键相同的对象用集合存储

@Test
public void test22(){
    Map<Integer,List<User>> userMap = new HashMap<>();
    List<User> userList = null;
    for (int i = 0; i < users02.size(); i++) {
        User user = users02.get(i);
        if(userMap.get(user.getAge())==null){
            userList = new ArrayList<>();
        }
        userList.add(user);
        userMap.put(user.getAge(),userList);
    }
    for(Integer key : userMap.keySet()){
        System.out.println("key:"+key+"\n"+"value:"+userMap.get(key));
    }
}

10、List集合转Map任意一个属性作为键,键相同的对象用集合存储(Java8新特性实现)

@Test
public void test23(){
    Map<Integer, List<User>> listMap = users02.stream().collect(Collectors.groupingBy(User::getAge));
    listMap.keySet().forEach(key->{
        System.out.println(key);
        listMap.get(key).forEach((user)->System.out.println(user));
    });
    for(Integer key : listMap.keySet()){
        System.out.println("key:"+key+"\n"+"value:"+listMap.get(key));
    }
}

11、取出users01中age一样的,并算出有几项

@Test
public void test03() {
    List<User> userList = users01.stream().filter(user1 -> users01.stream().filter((user2 -> user2.getAge().equals(user1.getAge()))).count() > 1l)
        .collect(toList());

    userList.stream().forEach((user) -> {
        System.out.println(user.getName() + ":" + user.getAge());
    });
    Map<Object, Object> str = new HashMap<>();
    for (User user : userList) {
        List<User> collect = userList.stream().filter(d -> d.getAge().equals(user.getAge())).collect(toList());
        str.put(user.getAge(), collect.size());
    }
    for (Object key : str.keySet()) {
        String value = str.get(key).toString();//
        System.out.println("key:" + key + " value:" + value);
    }
}

12、取出users01中的Id在users02中没有的user

/**
     * allMatch——检查是否匹配所有元素
     * anyMatch——检查是否至少匹配一个元素
     * noneMatch——检查是否没有匹配的元素
     */
//4.取出users01中的Id在users02中没有的user
@Test
public void test04() {
    //取出所有users02的id
    List<Integer> user02Ids = users02.stream().map(User::getId).collect(toList());
    System.out.println(user02Ids);
    List<User> userList = users01.stream().filter(user1 -> !user02Ids.stream().anyMatch(user02Id -> user1.getId().equals(user02Id))).collect(toList());
    userList.stream().forEach((user) -> {
        System.out.println(user.getName() + ":" + user.getAge());
    });



    List<SkuEsModel.Attrs> attrList = baseAttrs.stream().filter(item -> {
        // 过滤掉不包含在 searchAttrIds集合中的元素
        return idSet.contains(item.getAttrId());
    }).collect(Collectors.toList());
}

13、去掉users01name重复的只保留一个

@Test
public void test07() {
    List<User> userList = users01.stream().collect(
        Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName()))),
                                     ArrayList::new));
    userList.stream().forEach((user) -> {
        System.out.println(user.getName() + ":" + user.getAge() + ":" + user.getBirthday());
    });
}

14、将Student信息注入到相应的Grade里面的studentList中

List<Student> stuList = Arrays.asList(
    new Student(1, "张三", 1),
    new Student(2, "李四", 2),
    new Student(3, "李飞", 2)
);

List<Grade> gradeList = Arrays.asList(
    new Grade(1, "大一"),
    new Grade(2, "大二")
);

//13.将Student信息注入到相应的Grade里面的studentList中
@Test
public void test13() {
    gradeList.stream().forEach((grade) -> {
        List<Student> students = stuList.stream().filter((stu) -> stu.getGradeId().equals(grade.getGradeId())).collect(toList());
        grade.setStudentList(students);
    });
    gradeList.stream().forEach(grade -> {
        System.out.println(grade.getGradeName() + "---");
        grade.getStudentList().stream().forEach(stu -> {
            System.out.println(stu.getStuName());
        });
    });
}

JDK8 新特性 Stream API 进阶 (结合案例详解--通透--讲清)

如果这篇【文章】有帮助到你💖,希望可以给我点个赞👍,创作不易,如果有对Java后端或者对spring, 分布式, 云原生感兴趣的朋友,请多多关注💖💖💖
👨‍🔧 个人主页 : 阿千弟
文章来源地址https://www.toymoban.com/news/detail-460814.html

到了这里,关于JDK8 新特性 Stream API 进阶 (结合案例详解--通透--讲清)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • JDK8新特性之方法引用【 ::】

    接下来看看由辉辉所写的关于方法引用的相关操作吧 目录 🥳🥳Welcome Huihui\\\'s Code World ! !🥳🥳 一.是什么 二.为什么要用 三.什么时候用 四.怎么用 常见的引用方式  符号表示: “ ::” 是一种引用运算符,它所在的表达式称为方法引用  1.简化代码 方法引用可以将复杂的代

    2024年02月11日
    浏览(29)
  • JDK8,JDK11,JDK17,JDK21及中间版本主要更新特性

    官方地址: https://www.oracle.com/java/technologies/java-se-support-roadmap.html 从上图可以很清晰得可以看出,JDK7,JDK8,JDK11,JDK17,JDK21是长期维护的版本。从目前来看,JDK8到2023年已经有将近10年的历史了,大多数依据JDK8的相关技术内容已经很成熟了,但是大家也看到,JDK在不断地迭代,JD

    2024年02月21日
    浏览(48)
  • JDK8到JDK17有哪些吸引人的新特性?

    作者:京东零售 刘一达 2006年之后SUN公司决定将JDK进行开源,从此成立了OpenJDK组织进行JDK代码管理。任何人都可以获取该源码,并通过源码构建一个发行版发布到网络上。但是需要一个组织审核来确保构建的发行版是有效的, 这个组织就是JCP(Java Community Process)。2009年,SUN公

    2023年04月18日
    浏览(40)
  • jdk8对象列表使用stream流基于某个字段(或某些条件)实现去重

    直接上代码:(实现了去重加排序的效果) comparing(比较器)定义的就是去重的所使用的字段,可以使用匿名内部类来写更复杂的去重逻辑。 我们看看单参数的比较器方法实现;如下,可以发现内部实际调用效果类似于(a,b)-a.getXXX.conpareTo(b.getXXX)。 因为Function.apply(field)实际上

    2024年02月11日
    浏览(31)
  • JDK8的lambda方式List多字段排序List.stream().sorted()

    JDK8的lambda方式List多字段排序List.stream().sorted() 多字段排序 拼音排序: 引入jar包: 自定义比较器: 结束。

    2024年02月10日
    浏览(32)
  • JDK8、JDK11、JDK17和JDK21这几个版本更新的主要特性

    JDK8 是 Java 的一个重大更新版本,引入了一系列新特性和改进,主要包括: Lambda 表达式: Lambda 表达式允许我们以简洁、函数式的方式编写代码,使代码更易于理解和维护。- Stream API : Stream API 提供了一套声明式处理数据的方式,使得对集合和数组的操作更加直观和高效。

    2024年04月29日
    浏览(38)
  • Java语法理论和面经杂疑篇《十一. JDK8新特性》

    目录 1. Java版本迭代概述 1.1 发布特点(小步快跑,快速迭代) 1.2 名词解释 1.3 各版本支持时间路线图 1.4 各版本介绍 1.5 JDK各版本下载链接 1.6 如何学习新特性 2. Java8新特性:Lambda表达式 2.1 关于Java8新特性简介 2.2 冗余的匿名内部类 2.3 好用的lambda表达式 2.4 Lambda 及其使用举例

    2023年04月22日
    浏览(29)
  • Java—JDK8新特性—Lambda表达式【内含思维导图】

    目录 JDK8新特性 2.Lambda表达式 思维导图 2.1 什么是Lambda表达式 2.2 为什么使用Lamdba表达式 2.3 Lambda表达式基本语法 2.4 类型推断 2.5 Lambda练习 2.6 Lambda常用场景         官网提供网址:JDK 8 Features         Lamdba是一个 匿名函数 ,可以把Lamdba表达式理解为是一段可以传递的

    2024年02月03日
    浏览(33)
  • JDK8-JDK17中的新特性(var类型推断、模式匹配、Record、密封类)

    新的语法结构,勾勒出了 Java 语法进化的一个趋势,将开发者从 复杂、繁琐 的低层次抽象中逐渐解放出来,以更高层次、更优雅的抽象,既 降低代码量 ,又避免意外编程错误的出现,进而提高代码质量和开发效率。 1.1 Java的REPL工具: jShell命令 JDK9的新特性 Java 终于拥有了

    2024年02月06日
    浏览(40)
  • 【从零开始学Java第64期】JDK8 关于日期时间的新特性

    本系列为:从零开始学Java,为千锋教育资深Java教学老师独家创作 致力于为大家讲解清晰Java相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【点个关注】持续追更~ 有技术类问题,也欢迎大家和我们交流讨论! 在上一篇文章中本系列内容给大家讲

    2024年02月07日
    浏览(32)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包