首页 > 其他分享 >Lambda 表达式总结

Lambda 表达式总结

时间:2023-03-19 12:33:48浏览次数:55  
标签:总结 int System Test User test out 表达式 Lambda

1 Lambda 表达式简介

​ Lambda 表达式是 JDK 8 的新特性,主要用于简化匿名内部类的定义,帮助用户方便、高效地书写优雅的代码。

​ Lambda 表达式实现的必须是一个接口,并且接口中只有一个抽象方法,可以有 Object 类的方法(equals 等)和 default 修饰的方法(JDK8 新特性,被 default 修饰的方法会有默认实现,子类可以不实现,所以不影响 Lambda 表达式的使用)。

​ 被 @FunctionalInterface 注解修饰的接口,表示函数式接口,只有一个抽象方法,它和 lambda 表达式通常一起出现,JDK 也提供了大量的函数式接口供用户使用,如:Consumer、Supplier、Function、Predicate(四大核心函数式接口)等。

​ 通常,在定义匿名内部类的时候,也创建了一个对象,如下:

interface Test {
    public void fun();
}

//1.普通写法
Test test = new Test() {
    @Override
    public void fun() {
        System.out.println("xxx");;
    }
};
test.fun(); //打印:xxx

//2.Lambda 表达式写法
Test test = () -> System.out.printf("xxx");
test.fun(); //打印:xxx

​ 可以看到,Lambda 表达式使代码看起来非常简洁优雅。

2 Lambda 表达式语法

2.1 基础用法

​ Lambda 表达式主要用于简化匿名内部类的定义,并且被实现的接口只有一个抽象方法,因此本节将对此抽象方法的入参个数展开讨论。

(1)无参数

interface Test {
    public void fun();
}

//1.一条语句
Test test = () -> System.out.println("xxx");
test.fun(); //打印:xxx

//2.多条语句
Test test = () -> {
    System.out.println("xxx");
    System.out.println("yyy");
};
test.fun(); //打印:xxx \n yyy

​ 当接口中的抽象方法有返回值时, Lambda 表达式 使用方法如下:

interface Test {
    public int fun();
}

//1.一条语句,并且是 return 语句
Test test = () -> 1 + 1;
int a = test.fun();
System.out.println(a); //打印:2

//2.多条语句
Test test = () -> {
    int x = 1 + 1;
    return x + 1;
};
int a = test.fun();
System.out.println(a); //打印:3

(2)单参数

interface Test {
    public void fun(int x);
}

//Test test = x -> System.out.println(x);
Test test = (x) -> System.out.println(x);
test.fun(1); //打印:1

​ 入参为单参数时,可以省略入参小括号(见注释行)。

(3)多参数

interface Test {
    public void fun(int x, int y);
}

Test test = (x, y) -> System.out.println(x + y);
test.fun(1, 2); //打印:3

2.2 方法映射

​ 方法映射是指:将待重写的方法映射到一个已知方法,前提是:待映射的方法和目标方法的入参个数、类型和返回值类型一致。

interface Test {
    public int fun(int x, int y);
}

public class Main {

    public static void main(String[] args) {
        //1.映射到静态方法
        Test test1 = Main::add; //映射:fun -> add
        int a = test1.fun(1, 2);
        System.out.println(a); //打印:3

        //2.映射到实例方法
        Main main = new Main();
        Test test2 = main::subtract; //映射:fun -> subtract
        int b = test2.fun(1, 2);
        System.out.println(b); //打印:-1
    }

    private static int add(int x, int y) {
        return x + y;
    }

    private int subtract(int x, int y) {
        return x - y;
    }
}

2.3 构造方法

​ 需要创建的 User 类如下:

class User {
    String name;
    int id;

    User(){
        name = "张三";
        id = 1001;
    }

    User(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public String toString() {
        return "User{name: " + name + ", id: " + id +"}";
    }
}

(1)显式调用构造方法

​ 显式调用构造方法是指: 显式调用 new + 构造方法。

interface Test {
    public User newUser();
}

//1.无参构造方法
Test test = () -> new User();
User user = test.newUser();
System.out.println(user); //打印:User{name: 张三, id: 1001}

//2.有参构造方法
Test test = () -> new User("李四", 1002);
User user = test.newUser();
System.out.println(user); //打印:User{name: 李四, id: 1002}

(2)隐式调用构造方法

​ 隐式调用构造方法是指: 通过匹配待实现接口中的函数入参,自动选择相应的构造方法。

interface Test {
    public User newUser();
}

//1.无参构造方法
Test test = User::new; //自动匹配无参构造方法
User user = test.newUser();
System.out.println(user); //打印:User{name: 张三, id: 1001}
---------------------------------------------------------------

interface Test {
    public User newUser(String name, int id);
}

//2.有参构造方法
Test test = User::new; //自动匹配有参构造方法
User user = test.newUser("李四", 1002);
//User user = test.newUser(); //编译报错
System.out.println(user); //打印:User{name: 李四, id: 1002}

3 常用函数式接口

​ 函数式接口在一般在 java.util.function 包中,接口被 @FunctionalInterface 注解修饰,以保证接口中只有一个抽象方法,常用的函数式接口主要有:ConsumerPredicateFunctionComparator,用户可以根据入参个数和出参类型选择合适的函数式接口。

类型 类名 抽象方法 特点
消费型 Consumer void accept(T t) 执行对 T、U 的操作事件
BiConsumer void accept(T t, U u)
供给型 Supplier T get() 提供 T 类型对象
函数型 Function R apply(T t) 对 T、U 应用操作,并返回 R 类型对象
BiFunction R apply(T t, U u)
断言型 Predicate boolean test(T t) 判断 T、U 对象是否满足约束条件
BiPredicate boolean test(T t, U u)
其他 Comparator int compare(T o1, T o2) 定义 T 类型对象的大小属性

​ 说明:Comparator 不在 java.util.function 包中,而在 java.util 包中,Consumer、Supplier、Function、Predicate 并称为 Java 8 内置四大核心函数式接口。

​ 函数式接口在 Optional 中广泛应用(四大核心函数式接口都用到了),详见→Optional 详解

4 Lambda 表达式在集合中的应用

4.1 集合框架

​ 集合框架简图如下,详细见→Java容器及其常用方法汇总

img

4.2 遍历 List 元素(forEach)

(1)源码

​ Iterable.java

default void forEach(Consumer<? super T> action) {
	Objects.requireNonNull(action);
	for (T t : this) {
		action.accept(t);
	}
}

(2)应用

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 4,3,1,5,2);

//1.方法一
list.forEach(x -> System.out.print(x)); //打印:43152
//Consumer<Integer> consumer = x -> System.out.print(x);
//list.forEach(consumer);

//2.方法二
list.forEach(System.out::print); //打印:43152
//Consumer<Integer> consumer = System.out::print;
//list.forEach(consumer);

4.3 遍历 Map 元素(forEach)

(1)源码

​ Map.java

default void forEach(BiConsumer<? super K, ? super V> action) {
	Objects.requireNonNull(action);
	for (Map.Entry<K, V> entry : entrySet()) {
		K k;
		V v;
		try {
			k = entry.getKey();
			v = entry.getValue();
		}
		...
		action.accept(k, v);
	}
}

(2)应用

Map<Integer, String> map = new HashMap<>();
map.put(3, "qaz");
map.put(1, "wsx");
map.put(5, "edc");

map.forEach((i, s) -> System.out.print("(" + i + ", " + s +")")); //打印:(1, wsx)(3, qaz)(5, edc)
//BiConsumer<Integer, String> biConsumer = (i, s) -> System.out.print("(" + i + ", " + s +")");
//map.forEach(biConsumer);

4.4 删除元素(removeIf)

(1)源码

​ Collection.java

default boolean removeIf(Predicate<? super E> filter) {
	Objects.requireNonNull(filter);
	boolean removed = false;
	final Iterator<E> each = iterator();
	while (each.hasNext()) {
		if (filter.test(each.next())) {
			each.remove();
			removed = true;
		}
	}
	return removed;
}

(2)应用

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 4,3,1,5,2);

list.removeIf(x -> x == 3);
//Predicate<Integer> predicate = x -> x == 3;
//list.removeIf(predicate);

list.forEach(System.out::print); //打印:4152

4.5 排序元素(sort)

(1)源码

​ List.java

default void sort(Comparator<? super E> c) {
	Object[] a = this.toArray();
	Arrays.sort(a, (Comparator) c);
	ListIterator<E> i = this.listIterator();
	for (Object e : a) {
		i.next();
		i.set((E) e);
	}
}

(2)应用

List<Integer> list = new ArrayList<>();
Collections.addAll(list, 4,3,1,5,2);

list.sort((x, y) -> x - y);
//Comparator<Integer> comparator = (x, y) -> x - y;
//list.sort(comparator);

list.forEach(System.out::print); //打印:12345

4.6 多关键字排序

(1)源码

​ Comparator.java

default Comparator<T> thenComparing(Comparator<? super T> other) {
	Objects.requireNonNull(other);
	return (Comparator<T> & Serializable) (c1, c2) -> {
		int res = compare(c1, c2);
		return (res != 0) ? res : other.compare(c1, c2);
	};
}

​ 说明:thenComparing() 方法返回一个 Comparator 对象,其后可以再接多个 thenComparing() 方法,这里采用了职责链设计模式,详见→职责链模式

(2)应用

//先按 name 排序,再按 age 排序
userList.sort(Comparator.comparing(User::getName).thenComparing(User::getAge));

5 Lambda 表达式闭包问题

​ 匿名内部类通常定义在方法里,而方法里定义的变量都是局部变量,这时就可能存在此场景:匿名内部类访问方法中定义的局部变量。Java 语法要求:匿名内部类只能访问方法中定义的常量(被 final 修饰),否则会报错,如下:

img

​ Lambda 表达式放松了这一条件,但是在访问方法中定义的局部变量后,JVM 会自动将此变量改为常量,因此,之后修改此变量,会编译出错,如下:

img

​ 声明:本文转自Lambda 表达式总结

标签:总结,int,System,Test,User,test,out,表达式,Lambda
From: https://www.cnblogs.com/zhyan8/p/17232798.html

相关文章

  • 正则表达式(Regular Expression)详解
    1前言正则表达式主要用于复杂文本处理,如模式匹配、格式检验、文本替换等。常用的通配符有:^,$,*,.,,-,+,?,&,|,(),[],{}2String中的split()、matches()、r......
  • adb常用命令总结
    1前言​ADB(AndroidDebugBridge)即Android调试桥,采用监听SocketTCP端口的方式通讯。连接手机有2种方式:有线连接、无线连接。​(1)有线连接​使用数据线......
  • numpy数组初始化方法总结
    1使用list初始化a=np.array([[1,2,3],[4,5,6]],dtype='float32')#a=[[1.2.3.],[4.5.6.]]2赋值与复制(1)赋值a=np.array([1,2,3])b=aprint(bisa)#Trueb[0]......
  • 【RPC高性能框架总结】5.高性能nio框架netty(中)
    接上一篇《​​4.高性能nio框架netty(上)​​》上一篇我们编写了使用Netty框架开发的客户端的启动类“NettyTestClient”以及业务处理类“NettyTestClientHandler”,本篇我......
  • 【Docker学习总结】8.Docker-查看和删除镜像
    上一篇技术总结,我们使用常用的Docker命令创建了容器,并在容器中搭建了Nginx环境、部署了一个静态网页,并成功在宿主机中访问容器中的静态网页,以及使用浏览器在宿主机映射容器......
  • 【Java邮件开发】3.邮件协议总结与邮件服务器的工作原理
    我们来对邮件协议进行总结,并探讨邮件服务器的工作原理一、邮件协议剖析1.指令过程描述记得上一篇总结,我们手动敲指令发邮件的时候,登录smtp服务器的......
  • 李沐多模态串讲视频总结 ALBEF VLMo BLIP CoCa BEITv3 模型简要介绍
    开场多模态串讲的上篇是比较传统的多模态任务多模态最后的模态交互很重要传统的缺点是都用了预训练的目标检测器,训练和部署都很困难。ViLT把预训练的目标检......
  • Git常用命令总结
    1简介Git是一个开源的分布式版本控制系统,最初由LinusTorvalds为管理Linux内核而开发的开源软件,目前已应用在windows等操作系统上。SVN也是一种版本控制系统,但......
  • 记录生活感悟,总结归纳技术,提供行业解决方案
    经过重新梳理,网站上线了。欢迎访问,欢迎留言呀,网址:bytes.com.cn 站点共设三个部分。一是博客文章,记录有趣或者有用的文字,相当于日记本了。二是技术知识点汇总,多年的工作经......
  • 3月17日总结
    includeusingnamespaceQtDataVisualization;intmain(intargc,char**argv){QGuiApplicationapp(argc,argv);Q3DScatterscatter;scatter.setFlags(scatter.f......