01.什么是 lambda 表达式

1. 函数式接口

在聊起 lambda 表达式之前,我们不得不提起函数式接口:一个接口只包含唯一的方法,那么它就是函数式接口。例如:

public class LambdaTest {

    public static void main(String[] args) {
Lambda lambda=new SonLambda();
lambda.say();
}
} //1.一个接口只包含一个方法就是函数式接口
interface Lambda {
void say();
}
//2.一个类实现接口,要重写这个接口的所有方法
class SonLambda implements Lambda {
@Override
public void say() {
System.out.println("i love lambda");
}
}

有时候太懒的话我们会直接写一个匿名内部类

public class LambdaTest {
public static void main(String[] args) {
//2.匿名内部类: 没有子类,必须借助接口或者父类
Lambda lambda=new Lambda() {
@Override
public void say() {
System.out.println("i like lambda");
}
};
lambda.say();
}
}
//1.一个接口只包含一个方法就是函数式接口
interface Lambda {
void say();
}

但是我们写代码肯定是越懒(简单)越好,这个时候 Lambda 表达式闪亮登场。

Lambda表达式是 Java8 发布的最重要的新特性,它的出现就是为了解决匿名内部类那一坨坨代码的问题,让代码看起来更简洁。

lambda 表达式的语法格式如下:

(parameters) -> expression
或者
(parameters) ->{ statements;}

parameters 是参数,expression 是表达式。

对于上面例子中的匿名内部类,我们用 Lambda 表达式该怎样表示呢?

因为上面例子中匿名内部类只有一个方法,所以我们可以省略掉它的接口名和方法名。

又因为没有参数,所以我们直接可以用一个中括号表示它的方法名,然后用->指向它的方法体。如下所示:() -> {}替代了匿名内部类。

public class LambdaTest {
public static void main(String[] args) {
Lambda lambda=()->{
System.out.println("i like lombda");
};
lambda.say();
}
}
//1.一个接口只包含一个方法就是函数式接口
interface Lambda {
void say();
}

那么你可能会问,带有参数的接口用 lambda 表达式该怎样表示呢?

如下所示:

public class LambdaTest {
public static void main(String[] args) {
Lambda lambda=(a,b)->{
System.out.println("a="+a+" b="+b);
};
lambda.say(1,2);
}
}
//1 一个接口只包含一个方法就是函数式接口
interface Lambda {
void say(int a,int b);
}

02.Lambda 表达式常用方法

1. forEach 遍历集合中的元素

List<String> fruits= Arrays.asList("apple", "orange", "banana");
fruits.forEach(fruit->{
System.out.println("水果:"+fruit);
});

2. stream流

Java8中的 stream 是对集合功能的增强,它专注于对集合进行各种非常便利、高效的聚合操作,或者大批量数据操作。

3. map()

获取集合中的某一个元素,返回新的集合。记住使用map之前首先要获得集合的 stream 流。

public class LambdaTest {
public static void main(String[] args) {
//新增三个人的信息
ArrayList<User> list = new ArrayList<>();
list.add(new User(1,"张无忌",25));
list.add(new User(2,"赵敏",24));
list.add(new User(3,"周芷若",23));
//获取这三个人的所有名字
List<String> nameList = list.stream().map(User::getName).collect(Collectors.toList());
//遍历所有人的名字
nameList.forEach(name->{
System.out.println("名字:"+name);
});
}
}

4. collect(Collector c)

将操作之后的结果转换为集合,Collector 除了可以转为list集合,还能转为set集合,也就是不重复的集合。

public class LambdaTest {
public static void main(String[] args) {
//新增三个人的信息
ArrayList<User> list = new ArrayList<>();
list.add(new User(1,"张无忌",25));
list.add(new User(2,"张无忌",24));
list.add(new User(3,"周芷若",23));
//获取这三个人的所有名字
Set<String> set = list.stream().map(User::getName).collect(Collectors.toSet());
//遍历所有人的名字
set.forEach(name->{
System.out.println("不重复的名字:"+name);
});
}
}

5. distinct() 去重

public class LambdaTest {
public static void main(String[] args) {
//新增三个人的信息
ArrayList<User> list = new ArrayList<>();
list.add(new User(1,"张无忌01",25));
list.add(new User(2,"张无忌01",24));
list.add(new User(3,"赵敏",23));
//获取这三个人的所有名字
List<String> nameList = list.stream().map(User::getName).distinct().collect(Collectors.toList());
//遍历所有人的名字
nameList.forEach(name->{
System.out.println("去重之后的名字:"+name);
});
}
}

6. reduce()

将元素中的值以某种方式连接起来,SQL中类似 sum()、avg() 或者 count() 的聚集函数,实际上就是 reduce 操作,因为它们接收多个值并返回一个值。

public class LambdaTest {
public static void main(String[] args) {
//新增三个人的信息
ArrayList<User> list = new ArrayList<>();
list.add(new User(1,"张无忌",25));
list.add(new User(2,"周芷若",24));
list.add(new User(3,"赵敏",23));
//1.获取这三个人的年龄之和
//2.map(w -> w.getAge()) 获取每一个人的年龄
//3.reduce((x, y) -> x + y) 将他们的年龄相加
//4.get() 获取最后的结果
Integer sumAge = list.stream().map(w -> w.getAge()).reduce((x, y) -> x + y).get();
System.out.println("这三个人的年龄之和:"+sumAge);
}
}

7. match用法

allMatch():检查是否匹配所有元素

anyMatch(): 检查是否匹配任意元素

noneMatch(): 检查是否没有匹配元素

public class LambdaTest {
public static void main(String[] args) {
//新增三个人的信息
ArrayList<User> list = new ArrayList<>();
list.add(new User(1,"张无忌",25));
list.add(new User(2,"周芷若",24));
list.add(new User(3,"赵敏",23));
boolean result01 = list.stream().allMatch(w->w.getAge()>23);
boolean result02= list.stream().anyMatch(w->w.getAge()>23);
boolean result03= list.stream().noneMatch(w->w.getAge()>23);
System.out.println("所有人都大于23岁吗?:"+result01);
System.out.println("有大于23岁的吗?:"+result02);
System.out.println("他们没有大于23岁的吗?:"+result03);
}
}

8. filter() 条件过滤

public static void main(String[] args) {
//新增三个人的信息
ArrayList<User> list = new ArrayList<>();
list.add(new User(1,"张无忌",25));
list.add(new User(2,"周芷若",24));
list.add(new User(3,"赵敏",23));
//1.filter(w -> w.getAge() > 23) 年龄大于23
//2.map(w -> w.getName()) 获取人的名字
//3.获取这三个人中年龄大于23岁的人的名字的集合
List<String> nameList = list.stream().filter(w -> w.getAge() > 23).map(w -> w.getName()).collect(Collectors.toList());
nameList.forEach(name->{
System.out.println("年龄大于23岁的人:"+name);
});
}

9. sorted() 排序

public static void main(String[] args) {
//新增三个人的信息
ArrayList<User> list = new ArrayList<>();
list.add(new User(1,"张无忌",25));
list.add(new User(2,"周芷若",24));
list.add(new User(3,"赵敏",23));
//1.sorted(Comparator.comparing(User::getAge)) 根据某个字段排序
//2.reversed() 从大到小排序
List<User> users1 = list.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
System.out.println("-------------年龄从小到大排序");
users1.forEach(user->{
System.out.println(user.getName()+" "+user.getAge());
});
System.out.println("-------------年龄从大到小排序");
List<User> users2 = list.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
users2.forEach(user->{
System.out.println(user.getName()+" "+user.getAge());
}); }

03.Lambda表达式常见案例

  1. 案例一:获取所有用户的ID。
List<Integer> ids = list.stream().map(w -> w.getId()).collect(Collectors.toList());
  1. 案例二:将所有用户的 ID 作为 key , name 作为 value 放到一个map里面。
Map<Integer, String> userMap = list.stream().collect(Collectors.toMap(User::getId,User::getName));
  1. 案例三 :使用 stream 转换为集合,我们再也不用一个个去add了。
List<User> users = Stream.of(user1, user2, user3).collect(Collectors.toList());
  1. 案例四:map 对象转换,我们一般从数据库查数据为 PO 对象,返回给web端时一般为 VO 对象,那么这其中就涉及对象转换返回,map 就提供了便利的操作。
List<UserVo> userVos = userList.stream().map(user -> {
UserVo userVo = new UserVo();
BeanUtils.copyProperties(user, userVo);
return userVo;
}).collect(Collectors.toList());
  1. 案例五:按照某一个属性进行分组,比如这里我们按照用户性别进行分组。
Map<Integer, List<User>> genderGroup = userList.stream().collect(Collectors.groupingBy(User::getSex, Collectors.toList()));
  1. 案例六:求最小、最大、平均值、求和。
int min = userList.stream().mapToInt(User::getAge).min().orElse(-1);
int max = userList.stream().mapToInt(User::getAge).max().orElse(-1);
int sum = userList.stream().mapToInt(User::getAge).sum();
double average = userList.stream().mapToInt(User::getAge).average().orElse(-1);

04.写到最后

注意:lambda 表达式有个限制,那就是只能引用final或final局部变量,这就是说不能在lambda内部修改定义在域外的变量,不然会报错。

微信公众号:eclipse编程。专注于编程技术分享,坚持终身学习。

学会lambda表达式,能让你少敲1000行代码!的更多相关文章

  1. 爬数据,能让你少写1000行代码的捷径! | Python 正则表达式

    ▌春暖花开,又到了出门游玩拍拍拍吃吃吃的好季节了! 说到拍照摄影,你会构图吗?就是在照片有限的空间内处理人.景.物的关系,并将三者安排在画面中最佳的位置,以形成画面特定结构的方法. 学院君就是一个「拍 ...

  2. Java8 Lambda表达式和流操作如何让你的代码变慢5倍

    原文出处:ImportNew 有许许多多关于 Java 8 中流效率的讨论,但根据 Alex Zhitnitsky 的测试结果显示:坚持使用传统的 Java 编程风格——iterator 和 for- ...

  3. Java基础进阶:内部类lambda重点摘要,详细讲解成员内部类,局部内部类,匿名内部类,Lambda表达式,Lambda表达式和匿名内部类的区别,附重难点,代码实现源码,课堂笔记,课后扩展及答案

    内部类lambda重点摘要 内部类特点: 内部类可以直接访问外部类,包括私有 外部类访问内部类必须创建对象 创建内部对象格式: 外部类.内部类 对象名=new外部类().new内部类(); 静态内部类 ...

  4. C#中的Lambda表达式和表达式树

    在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...

  5. Java 8 Lambda表达式10个示例【存】

    PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...

  6. 【Java学习笔记之三十一】详解Java8 lambda表达式

    Java 8 发布日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Java 8之前 ...

  7. Kotlin——从无到有系列之高级篇(一):Lambda表达式

    如果您对Kotlin很有兴趣,或者很想学好这门语言,可以关注我的掘金,或者进入我的QQ群大家一起学习.进步. 欢迎各位大佬进群共同研究.探索 QQ群号:497071402 进入正题 经过前面一系列对K ...

  8. java8 快速入门 lambda表达式 Java8 lambda表达式10个示例

    本文由 ImportNew - lemeilleur 翻译自 javarevisited.欢迎加入翻译小组.转载请见文末要求. Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发 ...

  9. Java8 lambda表达式10个示例

    Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Ja ...

随机推荐

  1. Shell 编程(一)

    为什么学习 Shell 编程? 用 shell 来进行服务器的管理或维护 对于大数据程序员来说,需要编写 shell 来管理集群 Shell 是什么?   Shell 是一个命令解释器,它为用户提供了 ...

  2. 最全Java面试题(一)

    一.基础篇 1.1 java基础 面向对象的特征:继承.封装和多态 final, finally, finalize 的区别 final用于声明属性.方法和类,分别表示属性不可变.方法不可覆盖.类不可 ...

  3. jupyter安装插件Nbextensions,实现代码提示功能(终极方法)

    jupyter安装插件,实现代码提示功能 第一步 pip install jupyter_contrib_nbextensions -i https://mirrors.tuna.tsinghua.e ...

  4. 吃透论文——推荐算法不可不看的DeepFM模型

    大家好,我们今天继续来剖析一些推荐广告领域的论文. 今天选择的这篇叫做DeepFM: A Factorization-Machine based Neural Network for CTR Pred ...

  5. go判断字符串是否是IP地址

    前言 现在有这样的需求 正文 使用net包 net包的方法可以判断是否是 ip,需要注意的是 ip 分为 ipv4 和 ipv6 此方法将 v4 和 v6 一起判断出来 address := net. ...

  6. 【Linux】kali 安装 python3 和 pip3(亲测有效)

    [Linux]kali 安装 python3 和 pip3 引言:   在使用kali的时候,经常会用到各种工具以及脚本,而大多数脚本都是以python编写的,但是烦就烦在python有2个版本,有些 ...

  7. Java Mybatis快速入门之基本使用

    目录 搭建环境 编写 Mybatis 核心配置文件 pom导出资源失败 测试 搭建环境 新建Maven项目 导入Maven依赖 <dependencies> <!--mysql驱动- ...

  8. 安装Tomcat 9

    文章目录 访问Tomcat官网 选择下载所需的软件包 安装Tomcat 测试安装 访问Tomcat官网 Tomcat官方的下载地址为:https://tomcat.apache.org/downloa ...

  9. 【Java】Java关键字、含义

    Java关键字 来自 Java 核心技术卷I 基础知识(原书第10 版)/( 美)凯S 霍斯特曼(Cay S . Horstmann )著: 周立新等译一北京:机械工业出版社, 2016 . 8 Ja ...

  10. LeetCode965. 单值二叉树

    题目 1 class Solution { 2 public: 3 int flag = 0; 4 bool isUnivalTree(TreeNode* root){ 5 isUnivalTree1 ...