惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
云风的 BLOG
云风的 BLOG
IT之家
IT之家
S
Secure Thoughts
U
Unit 42
G
GRAHAM CLULEY
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
N
News and Events Feed by Topic
The Cloudflare Blog
月光博客
月光博客
V
Visual Studio Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Schneier on Security
Schneier on Security
O
OpenAI News
Hacker News - Newest:
Hacker News - Newest: "LLM"
P
Privacy International News Feed
The Hacker News
The Hacker News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Tailwind CSS Blog
SecWiki News
SecWiki News
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Simon Willison's Weblog
Simon Willison's Weblog
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
C
Check Point Blog
D
Docker
Scott Helme
Scott Helme
Engineering at Meta
Engineering at Meta
博客园_首页
W
WeLiveSecurity
MongoDB | Blog
MongoDB | Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Vulnerabilities – Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
J
Java Code Geeks
NISL@THU
NISL@THU
S
Security Affairs
C
Cybersecurity and Infrastructure Security Agency CISA
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 编程我的一切

Apache Hop实战:Windows平台MySQL数据迁移的深度排错与性能调优 线程与进程的区别与联系:操作系统入门详解(含 Python 示例) 打破同源枷锁:深入理解 postMessage 跨域通信机制 三大搜索引擎 URL 推送 API 详解:百度、必应、谷歌 PandasAI:当数据分析遇上自然语言处理 Windows 左ctrl和左alt键互换 Bootstrap下拉菜单、按钮式下拉菜单 SSM三大框架的运行流程、原理、核心技术详解 app启动速度怎么提升? canvas画布基本知识点总结 SSM框架整合(Spring + SpringMVC + MyBatis) Spring boot+CXF开发WebService Demo HTML5中的Web Notification桌面通知 Open3d之交互式可视化 行为识别TSM训练ucf101数据集 Python3列表、元组及之间的区别和转换 Java 字符串简介 Shell从入门到精通 基于go-cqhttp实现QQ机器人
Lambda入门
编程我的一切 · 2021-02-09 · via 博客园 - 编程我的一切

本文是Lambda的入门文章。主要向读者介绍Lambda的基本概念和写法。主要面向的读者是Java新手。

 主要内容:

  • Lambda到底是什么东西?
  • 怎么通过Lambda简化代码?

背景知识:其中在逐步推导Lambda表达式时,需要用到并发编程中的Runnable接口。

目录

什么是Lambda

第一个Lambda表达式

原始写法

静态内部类简化

局部内部类简化

匿名内部类简化

Lambda简化

再简化

Lambda实例


什么是Lambda

基本特性:

  1. 是JDK1.8开始之后的新技术,是一种代码的新语法。
  2. 目的是为了简化匿名内部类的代码写法

使用前提:

  1. 首先必须是接口。
  2. 接口中只能有一个抽象方法。
  3. 即,Lambda表达式只能简化接口中只有一个抽象方法的匿名内部类形式。

函数式接口:

  1. 接口中只有一个抽象方法的接口称为函数式接口。
  2. 函数式接口注解:@FunctionalInterface 一旦某个接口加上了这个注解,这个接口只能、有且仅有一个抽象方法。

Lambda 语法

  1. (params) -> expression
  2. (params) -> statement
  3. (params) -> { statements }
  4. 左侧:Lambda 表达式的参数列表;右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体

第一个Lambda表达式

在并发编程中,我们可以通过实现Runnable接口来开辟一个新的任务线程。下面,通过任务线程的代码编写,来理解Lambda是如何简化写法的。

原始写法

首先明确,Runnable接口只有一个方法,满足函数式接口的条件:

以下是常规的写法:

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyThread()); //创建一个线程
        thread.start(); //执行线程
    }
}

//实现Runnable接口,实现任务线程
class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
    }
}

静态内部类简化

将线程任务类放在要调用内的内部,作为静态内部类或者成员内部类:

public class Main {
    //实现Runnable接口,实现任务线程
    public static class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
        }
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new MyThread()); //创建一个线程
        thread.start(); //执行线程
    }
}

局部内部类简化

把任务线程放在方法体内、局部变量的位置:

public class Main {
    public static void main(String[] args) {
        class MyThread implements Runnable { //局部内部类,就相当于申明一个变量
            @Override
            public void run() {
                System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
            }
        }

        Thread thread = new Thread(new MyThread()); //创建一个线程
        thread.start(); //执行线程
    }
}

匿名内部类简化

省略实现类类名的方式,其中“new Runnable() {}”,等价于“class 名字 implements Runnable() {}”:

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
            }
        }); //申明任务线程

        thread.start(); //执行线程
    }
}

Lambda简化

Lambda的简化格式:

   (匿名内部类被重写方法的形参列表) -> {

       被重写方法的方法体代码。

   }

Lambda简化:

public class Main {
    public static void main(String[] args) {

        //使用Lambda简化:
        // 把"public void run()"简化为"()"。
        // 之所以不用指定方法名,是因为函数式接口中有且仅有一个方法,只要一调用,只有那一个方法可以调用
        // 方法体保持不变
        Thread thread = new Thread( () -> {
            System.out.println("线程"+Thread.currentThread().getName()+"执行了!");
        });
        thread.start();
    }
}

再简化

再简化:
public class Main {
    public static void main(String[] args) {
        //方法体内只有一行代码,可以直接去掉方法体的花括号:{}
        Thread thread = new Thread(() -> System.out.println("线程"+Thread.currentThread().getName()+"执行了!") );
        thread.start();
    }
}


匿名对象的简化:
public class Main {
    public static void main(String[] args) {
        //把Thread类转换为匿名对象
        new Thread(() -> System.out.println("线程"+Thread.currentThread().getName()+"执行了!")).start();
    }
}

Lambda实例

Lambda简化Comparator接口匿名内部类写法:

public static void main(String[] args) {
    List<Student> lists = new ArrayList<>();
    Student s1 = new Student("李铭",18,'男');
    Student s2 = new Student("冯龙",23,'男');
    Student s3 = new Student("王乐乐",21,'男');
    Collections.addAll(lists , s1 , s2 , s3);

    // 按照年龄进行升序排序!
    Collections.sort(lists, new Comparator<Student>() {
        @Override
        public int compare(Student s1, Student s2) {
            return s1.getAge() - s2.getAge();
        }
    });

    // Lambda简化写法
    Collections.sort(lists, (Student t1, Student t2) -> {
        return t1.getAge() - t2.getAge();
    });
    // 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。
    // 此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
    Collections.sort(lists,(Student t1, Student t2) -> t1.getAge() - t2.getAge());

    // 参数类型可以省略
    Collections.sort(lists, (t1,  t2) -> t1.getAge() - t2.getAge());

    System.out.println(lists);
}

forEach遍历简化

public static void main(String[] args) {
    List<String> names = new ArrayList<>();
    names.add("胡伟光");
    names.add("甘挺");
    names.add("洪磊");

    //forEach遍历原理
    names.forEach(new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    });

    //Lambda简化
    names.forEach((String s) -> {
        System.out.println(s);
    });

    //省略入参类型
    names.forEach((s) -> {
        System.out.println(s);
    });
    //如果只有一个参数,省略:入参括号
    names.forEach(s -> {
        System.out.println(s);
    });

    //Lambda表达式的方法体代码只有一行代码,省略花括号、分号
    names.forEach(s -> System.out.println(s) );

    names.forEach(System.out::println);
}

总结:

  • Lambda的作用是简化代码的写法,减少代码量。
  • 核心语法是:(参数1,参数2) -> { 方法体(如果方法体可以使用一句代码,则可以省略花括号) }