万字详解Stream流,聊聊工作中常用的Lambda表达式

前言


大家好,我是weichert。

在日常开发中,我们经常会用到JDK 8中的Lambda表达式,lambda表达式允许我们把函数作为一个方法的参数,实现复杂的功能。函数式编程相较于面向对象编程(OOP),可以使我们的代码更加简洁,更加优雅,可以使用更少的代码量,实现更加强大的功能。stream流针对于list的操作更加的简洁,集成了许多常用的api,供我们进行调用,极大的提高了我们的开发效率。在这篇文章中,我整理了在我工作中常用的一些Stream流,供大家学习参考。

  • 公众号、掘金账号: weichert

函数式接口原理


函数式接口是Java中的一种接口类型,它只包含一个抽象方法。使用@FunctionalInterface注解。,这个注解只可以标记在有且仅有一个抽象方法的接口上,并且JDK8接口中的静态方法和默认方法,都不算是抽象方法。常用函数式接口如Function等也随Lambda一同增加在了java.util.function包中。

在jdk8中底层的实现原理:在我们实际编写lambda表达式中,就是将该接口进行重写,我们只需要关注参数和返回值即可,例如Function中的参数泛型,返回值泛型。

jdk8中的函数式接口放在java.util.function目录下:

lambda表达式的写法


Java中lambda表达式符号:->

写法: (参数) -> {返回值}

生产型接口(无参数有返回值):( ) -> {业务代码,return 返回值}

消费型接口(有参数无返回值):(参数值) -> {业务代码,无返回值}

转换型接口(有参数有返回值):(参数值) -> {业务代码,return 返回值}

备注:

  • 当参数值只有一个时,()可以省略不写。 - 但业务代码只有一行时,{}可以省略不写。 - -> 符号,不可以省略。

示例:Thread类的函数式接口

java 复制代码
// 1.使用匿名内部类的方式创建多线程new Thread(new Runnable() {    @Override    public void run() {        System.out.println("这是多线程1");    }}).start();
// 2.使用lambda表达式的方式创建多线程表达式new Thread(() -> System.out.println("这是多线程2")).start();

Thread(函数式接口)

stream流常用方法


1.创建stream流

方式1:

java 复制代码
List<Integer> list = new ArrayList<>();Stream<Integer> stream = list.stream();

方式2:

java 复制代码
Stream<String> stream = Stream.of("张三", "李四", "王五");

备注: stream流创建后只能使用一次,创建了一个stream流使用两次会报IllegalStateException异常。

java 复制代码
@Testpublic void testReuseStream() {    Stream<Integer> stream = Stream.of(416, 1854, 157, 187);    stream.sorted().forEach(System.out::println);    stream.sorted(((o1, o2) -> o2-o1)).forEach(System.out::println);}

2.ForEach

forEach方法和Java中的for循环是一样,主要是是做遍历操作。**

**

该函数式接口为消费型接口,有参无返回值,并且是终结接口(表示处理结束)。

java 复制代码
public void testForEach(){        List<String> list = new ArrayList<String>() {{            add("1");            add("2");            add("3");        }};
        list.forEach(s-> System.out::println);    }

3.Collect

转化接口,我们经常使用该接口将stream流转换为list,该接口可以作为终结接口使用,collect(Collectors.toList())最常用。

java 复制代码
@Testpublic void testCollect(){    List<String> list = new ArrayList<String>() {{        add("1");        add("2");        add("2");    }};    //转换为新的list    List newList = list.stream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());}

4.Filter

这是一个过滤方法,就像一个过滤器,满足条件的才会保存起来,不满足条件的就会被过滤掉。

该函数式接口,返回值是一个布尔值,为true则保存,为false则丢弃。

java 复制代码
public void testFilter() {        List<String> list = new ArrayList<String>() {{            add("1");            add("2");            add("3");        }};                        list.stream()                // 过滤掉我们希望留下来的值                // 表示我们希望字符串是 1 能留下来                // 其他的过滤掉                .filter(str -> "1".equals(str))                .collect(Collectors.toList());}

5.Map

map 方法可以让我们进行一些流的转化,比如原来流中的元素是 A,通过 map 操作,可以使返回的流中的元素是 B,这是一个转换方法。

这是方法是所有方法中使用频率最高的,常见的转化操作都会使用该接口,比如将String类型的数据转换为Integer类型

java 复制代码
public void testMap() {        List<String> list = new ArrayList<String>() {{            add("1");            add("2");            add("3");        }};        //通过 map 方法list中元素转化成 小写        List<String> strLowerList = list.stream()                .map(str -> str.toLowerCase())                .collect(Collectors.toList());}

6.Distinct

distinct 方法类似于SQL中的去重操作,可以去掉重复的参数。

备注:对于引用数据类型的去重需要重写hashCode和equals方法。

java 复制代码
public void testDistinct(){        List<String> list = new ArrayList<String>() {{            add("1");            add("2");            add("2");        }};        list.stream()                .map(s -> Integer.valueOf(s))                .distinct()                .collect(Collectors.toList());    }

7.Sorted

Sorted 方法提供了排序的功能,并且允许我们自定义排序,可以正序,倒序,自定义规则排序等。

8.findFirst

这个方法就像SQL中的limit1一样,只会返回集合中的第一个元素,在获取第一名,最后一名这种操作下,常见。**

**

java 复制代码
@Testpublic void testCollect(){    List<String> list = new ArrayList<String>() {{        add("1");        add("2");        add("2");    }};    //转换为新的list    Optional<Integer> first = list.stream().map(s -> Integer.valueOf(s)).sorted().findFirst();}

9.Max,Min

这两个方法顾名思义是求集合中的最大值、最小值。

java 复制代码
public void testMaxMin(){        List<String> list = new ArrayList<String>() {{            add("1");            add("2");            add("2");        }};
        list.stream().max(Comparator.comparing(s -> Integer.valueOf(s))).get();        list.stream().min(Comparator.comparing(s -> Integer.valueOf(s))).get();    }

10.groupingBy

groupingBy 是能够根据字段进行分组,toMap 是把 List 的数据格式转化成 Map 的格式,类似于SQL中的group by。

java 复制代码
public void testGroupBy(){        List<String> list = new ArrayList<String>() {{            add("1");            add("2");            add("2");        }};
        Map<String, List<String>> strList = list.stream().collect(Collectors.groupingBy(s -> {            if("2".equals(s)) {                return "2";            }else {                return "1";            }        }));    }

总结


本文中,主要描述了lambda表达式的实现原理,核心关键点在于函数式接口,以及函数式接口的分类,十种stream流的常用方法。

归根结底,在使用stream时,我们只需要关注函数式接口的参数和返回值即可,根据函数式接口的要求,实现我们的业务代码,即可优雅的使用函数式接口,简化我们的代码。

stream流中的方法和MySQL中的一些函数,关键字的作用类似,都是对数据的处理操作。

stream流和MySQL中函数的区别

stream流 MySQL
min,max min,max
findFirst limit 1
groupingBy grouping by********
distinct distinct
sorted order by
filter where

最后


stream的使用,也是熟能生巧的事,群里面有小伙伴在交流该问题:

可以在公众号联系我进群哦!

只要多多练习就能熟练的掌握stream流的使用,帮助你优雅地写出高质量的代码。

欢迎关注公众号:weichert

每天分享一篇实用的技术文章,对面试,工作都有帮助

如果您觉得有收获,记得点赞,转发,分享,谢谢

相关推荐
Pandaconda2 分钟前
【计算机网络 - 基础问题】每日 3 题(十)
开发语言·经验分享·笔记·后端·计算机网络·面试·职场和发展
loveLifeLoveCoding4 分钟前
Java List sort() 排序
java·开发语言
草履虫·10 分钟前
【Java集合】LinkedList
java
AngeliaXue12 分钟前
Java集合(List篇)
java·开发语言·list·集合
世俗ˊ13 分钟前
Java中ArrayList和LinkedList的比较
java·开发语言
zhouyiddd18 分钟前
Maven Helper 插件
java·maven·intellij idea
攸攸太上26 分钟前
Docker学习
java·网络·学习·docker·容器
Milo_K34 分钟前
项目文件配置
java·开发语言
程序员大金38 分钟前
基于SpringBoot+Vue+MySQL的养老院管理系统
java·vue.js·spring boot·vscode·后端·mysql·vim
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS网上购物商城(JAVA毕业设计)
java·vue.js·spring boot·后端·开源