首页 > 编程语言 >java8中的lambda表达式实用详解

java8中的lambda表达式实用详解

时间:2022-08-20 11:14:47浏览次数:64  
标签:String System java8 详解 println lambda public Lambda

java8中的lambda表达式实用详解

1. lambda简介

​ Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。Lambda表达式是Java8中的新特性,编码一般是尽可能轻量级的将代码封装为数据,传统的解决方案是通过接口和实现类(匿名内部类)实现,这种方式存在语法冗余,this关键字,变量捕捉,数据控制等问题lambda概述

2. lambda特点

  • Lambda表达式理解为一段可以传递的代码,可以写出更简洁、更灵活的代码。

  • 使代码更简洁,紧凑

  • 可以使用并行流来并行处理,充分利用多核CPU的优势,有利于JIT编译器对代码进行优化

3. lambda经典案列

  • 线程创建的两种方式:继承Thread方式、实现Runnable方式
public interface Runnable{
    void run();
}
  • 匿名内部方式创建一个线程

Tread类传递了一个匿名的Runnable对象,重载Runnable接口的run()方法来实现相应逻辑。

public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override  //重写Runnable接口里面的run()方法
            public void run() {
                System.out.println("匿名内部类方式--线程1");
            }
        });
        thread.start(); //启动线程
}
  • Lambda表达式创建一个线程
public static void main(String[] args) {
    Thread thread = new Thread(
        () -> System.out.println("匿名内部类方式-启动线程2"));
    thread.start();
}

4.lambda语法格式

4.1 Lambda表达式的标准语法格式

Lambda表达式就是对函数式接口中抽象方法的实现,是对其匿名内部类的一个简写,只保留了方法的参数列表和方法体,其他的成分可以省略。因此,Lambda表达式的格式非常简洁,只有三部分组成:

  • 参数:指定了Lambda表达式需要的所有参数,如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
  • 箭头:由英文中画线和大于符号组成,固定写法。代表指向动作
  • 方法体:Lambda表达式要执行的功能,具体的代码方法内容
(参数,…,参数)->{方法体}

基本语法:(parameters) -> expression 或 (parameters) ->{ statements; }

注:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但无参数或多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

4.2 Lambda表达式省略语法格式

在Lambda标准语法格式的基础上,可以使用省略写法的规则:

  • 若小括号内参数只有一个可以省略。
  • 若小括号内没有参数或有两个及以上的参数,则 小括号不能省略。
  • 若大括号内只有一条语句,无论是否有返回值,大括号、return关键字、分号可以省略。
案例一:无参,无返回值,只有一条语句
public static void main(String[] args) {
        Runnable runnable = () -> System.out.println("lambda 运行1");
        runnable.run();
 }

//结果
lambda 运行1
案例二:一个参数,无返回值
public static void main(String[] args) {
        Consumer<String> consumer = (x) -> System.out.println(x);
        //可简化   Consumer<String> consumer = System.out::println;
        consumer.accept("lambda 运行2");
 }

//结果
lambda 运行2
案例三:一个参数时,参数的小括号可以省略
public static void main(String[] args) {
        Consumer<String> consumer3 = x -> System.out.println(x);
    	//可简化	Consumer<String> consumer3 = System.out::println;
        consumer3.accept("lambda 运行3");
 }

//结果
lambda 运行3
案例四:有两个参数,并且Lambda体中有多条语句。
public static void main(String[] args) {
        Comparator<Integer> com4 = (x, y) -> {
            System.out.println("lambda 运行4");
            return Integer.compare(x, y);
        };
        System.out.println(com4.compare(1, 2));
 }

//结果
lambda 运行4
-1
案例五:有两个以上参数,有返回值,若Lambda体中只有一条语句,return和大括号都可以省略不写
public static void main(String[] args) {
        Comparator<Integer> com5 = (x, y) -> Integer.compare(x, y);
    	//可简化	 Comparator<Integer> com5 = Integer::compare;
        System.out.println(com5.compare(1, 2));
 }

//结果
-1
案例六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM可以通过上下文推断出数据类型,即“类型推断”
public static void main(String[] args) {
       Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);
       //可简化 	Comparator<Integer> com = Integer::compare;
       System.out.println(com.compare(1, 2));
 }

//结果
-1

口诀:左右遇一括号省,左侧推断类型省,能省则省。

5. 方法引用

方法引用的三种形式

  • 类 :: 静态方法

  • 类 :: 非静态方法

  • 对象 :: 非静态方法

注:

方法引用规定,对象不能调用静态方法,这和面向对象的思想一致。但类可以调用非静态方法,这是面向对象中不允许的。

5.1 类引用静态方法

语法格式:类::静态方法名

public static void main(String[] args) {
    Comparator<Integer> comparable= Integer::compare;
    //使用方法引用实现相同效果
    Comparator<Integer> integerComparable=Integer::compare;
    System.out.println(integerComparable.compare(2,1));
    System.out.println(comparable.compare(2,1));
}

//结果
1
1
5.2 类引用普通方法

语法格式:类::实例方法名

public static void main(String[] args) {

    BiPredicate<String, String> biPredicate = String::equals;
    //使用方法引用实现相同效果
    BiPredicate<String, String> bp2 = String::equals;
    System.out.println(biPredicate.test("1", "2"));
    System.out.println(biPredicate.test("1", "2"));
}

//结果
false
false
5.3 对象引用非静态方法

语法格式: 实例化对象::普通方法;

public static void main(String[] args) {
    Consumer<String> consumer = System.out::println;
    consumer.accept("java");
}

//结果
java  

6. 构造引用

构造引用语法格式: 类名称::new

  • 和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致。

  • 抽象方法的返回值类型即为构造器所属的类的类型

//data:
public static class Employee {
           private Integer id;
           private String name;
           private Integer age;

           @Override
           public String toString() {
               return "Employee{" +
                       "id=" + id +
                       ", name='" + name + '\'' +
                       ", age=" + age +
                       '}';
           }
           public Employee(){

           }

           public Employee(Integer id) {
               this.id = id;
           }

           public Employee(Integer id, Integer age) {
               this.id = id;
               this.age = age;
           }

           public Employee(int id, String name, int age) {
               this.id = id;
               this.name = name;
               this.age = age;
           }
       }

实例:

public static void main(String[] args) {

    //原始写法
    Supplier<Employee> sup = new Supplier<Employee>() {
        @Override
        public Employee get() {
            return new Employee();
        }
    };

    // Lambda写法
    Supplier<Employee>  sup1 = () -> new Employee();

    //构造器引用写法
    //Supplier中的T get()
    //Employee的空参构造器:Employee()
    Supplier<Employee>  sup2 = Employee :: new;

}
// Lambda写法
Function<Integer,Employee> func1 = id -> new Employee(id);

//构造器引用写法
//Function中的R apply(T t)
Function<Integer,Employee> func2 = Employee :: new;
// Lambda写法
BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name);

//构造器引用写法
//BiFunction中的R apply(T t,U u)
BiFunction<Integer,String,Employee> func2 = Employee :: new;

7. 数组引用

数组引用的格式:type[]:new

public static void main(String[] args) {

    Function<Integer,String[]> function=String[]::new;
    String[] apply = function.apply(5);
    System.out.println(apply.length);
}

//结果
5

8. Lambda表达式的作用域

​ Lambda表达式可以看作是匿名内部类实例化的对象,Lambda表达式对变量的访问限制和匿名内部类一样,因此Lambda表达式可以访问局部变量、局部引用,静态变量,实例变量。

8.1 访问局部变量

可以直接在 lambda 表达式中访问外部的局部变量

public static void main(String[] args) {
final int num = 1;
//不用声明为final 也可以
//int num = 1;
Converter<Integer, String> stringConverter =
        (from) -> String.valueOf(from + num);

stringConverter.convert(2);
}

//结果
3
8.2 访问对象字段,静态变量

和局部变量不同的是,Lambda内部对于实例的字段(即:成员变量)以及静态变量是既可读又可写。

import org.springframework.core.convert.converter.Converter;

public static void main(String[] args) {

    Lambda4 lambda4 = new Lambda4();
    lambda4.testScopes();
}


class LambdaTest {
    static int myStaticNum;
    int myNum;
 
    void testScopes() {
        Converter<Integer, String> stringConverter1 = (from) -> {
            outerNum = 23;
            return String.valueOf(from);
        };
        String convert = stringConverter1.convert(1);
        System.out.println("Integer转化String结果" + convert);


        Converter<Integer, String> stringConverter2 = (from) -> {
            outerStaticNum = 72;
            return String.valueOf(from);
        };
        String convert2 = stringConverter2.convert(2);
        System.out.println("Integer转化String结果" + convert2);
    }
}


//结果
Integer转化String结果 1
Integer转化String结果 2

9. 总结

​ java8新特性之lambda表达式知识总结的文章就介绍到这了,这边列举了部分例子供参考,仅作为学习笔记使用,欢迎批评指正,要是感兴趣可以关注微信订阅号 程序own

标签:String,System,java8,详解,println,lambda,public,Lambda
From: https://www.cnblogs.com/ProgramOwn/p/16607331.html

相关文章

  • CTF_攻击目标主机获取root权限及flag全流程分析详解
    一、主机发现 1、nmap-sP192.168.178.1/24   //ping扫描C段   2、arp-scan-l             //感觉快一点 3、netdiscover-p......
  • Python PyInstaller安装和使用教程(详解版)
    在创建了独立应用(自包含该应用的依赖包)之后,还可以使用PyInstaller将 Python 程序生成可直接运行的程序,这个程序就可以被分发到对应的Windows或MacOSX平台上运行......
  • 另类数学分析 - 从lambda演算谈起
    注:这篇文章主要是写给自己和lcw看的,可能会比较混乱和难以理解默认的概念:对象:数学上一切皆可以看做对象。朴素的相等关系(\(=\not=\)):一个对象始终等于其本身,不等于其......
  • MySQL日志详解
    一、mysql日志日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql日志主要包括错误日志、二进制日志、查询日志、慢查询日志、事务日志(redolog......
  • Java8 Lamba Steam操作
    (1)、创建Stream:一个数据源(如:集合、数组),获取一个流(2)、中间操作:一个中间操作链,对数据源的数据进行处理(3)、终止操作(终端操作):一个终止操作,执行中间操作链,并产生结果1、生......
  • vue项目打包后使用reverse-sourcemap反编译到源码(详解版)
    首先得说一下,vue项目中productionSourceMap这个属性。该属性对应的值为true|false。  当productionSourceMap:true,时:1、打包后能看到xxxx.js.map文件,map文件够......
  • pytest系列——allure命令行参数详解
    一、查看allure命令的帮助文档allure-hallure命令的语法格式allure[options][command][commandoptions]options列表Options:--help命令行帮助文档......
  • sed命令详解
    sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(patternspace),接着用......
  • Jmeter(四十九) - 从入门到精通高级篇 - jmeter使用监视器结果监控tomcat性能(详解教程
    ------------------------------------------------------------------- 转载自:北京-宏哥https://www.cnblogs.com/du-hong/p/13667219.html -------------------------......
  • hibernate:映射文件hbm.xml详解
    转载:http://www.cnblogs.com/fingerboy/p/5233939.html实体类就是指普通的POJO,Hibernate并不知道那个实体类对应数据库的哪一张表,所以还需要配置一下,常用的方式就是*.......