JAVA基础 函数式编程 1

简介: JAVA基础 函数式编程

一、Lambda表达式

1.1 Lambda表达式介绍

Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

在Java语言中,可以为变量赋予一个值:

能否把一个代码块赋给一变量吗?

在Java 8之前,这个是做不到的。但是Java 8问世之后,利用Lambda特性,就可以做到了。

甚至我们可以让语法变得更简洁。


在Java 8里面,所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是”那段代码“,需要是这个接口的实现。这是我认为理解Lambda的一个关键所在,简而言之就是,Lambda表达式本身就是一个接口的实现。直接这样说可能还是有点让人困扰,我们继续看看例子。我们给上面的aBlockOfCode加上一个类型:


3df22641aa07334b4928460fa4e638b0.png

这种只有一个接口函数需要被实现的接口类型,我们叫它”函数式接口“。只要”函数式接口“才能使用Lambda表达式。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口”,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了。


aeac890ee74089c82c545302dab794d4.png

1.2 Lambda作用

最直观的作用就是使得代码变得异常简洁。

接口要求

虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。


jdk 8 中有另一个新特性:default, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。也就是说一个接口中有且仅有一个抽象方法,还有default实现的方法也能使用Lambda表达式。


@FunctionalInterface注解作用:


@FunctionalInterface标记在接口上,“函数式接口”是指仅仅只包含一个抽象方法的接口。

1.3 Lambda表达式语法

1.3.1 Lambda表达式结构

语法结构:

(parameters) -> expression

(parameters) ->{ statements;}


语法形式为 () -> {}:


() 用来描述参数列表,如果有多个参数,参数之间用逗号隔开,如果没有参数,留空即可;


-> 读作(goes to),为 lambda运算符 ,固定写法,代表指向动作;


{} 代码块,具体要做的事情,也就是方法体内容;

1.3.2 Lambda表达式的重要特征

可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

可选的参数圆括号”()“:一个参数无需定义圆括号,但多个参数需要定义圆括号。

可选的大括号”{ }“:如果主体包含了一个语句,就不需要使用大括号。

可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

// 1. 不需要参数,返回值为 5 
() -> 5 
// 2. 接收一个参数(数字类型),返回其2倍的值 
x -> 2 * x 
// 3. 接受2个参数(数字),并返回他们的差值 
(x, y) -> x – y 
// 4. 接收2个int型整数,返回他们的和 
(int x, int y) -> x + y 
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) 
(String s) -> System.out.print(s)

1.3 Lambda表达式使用

1.3.1 定义函数接口并使用Lambda表达式实现函数接口

函数接口指的是在该接口中只能含有一个抽象方法。可以有多个default修饰的方法或者是static方法。

package cn.it.bz.Lambda;
//无返回值无参数的函数接口
@FunctionalInterface
interface NoReturnNoParam{
    public void method();
}
//无返回值有一个参数的函数接口
@FunctionalInterface
interface NoReturnOneParam {
    public void method(int a);
}
//无返回值有两个参数的函数接口
@FunctionalInterface
interface NoReturnManyParam {
    public void method(int a, int b);
}
//有返回值的无参数函数接口
@FunctionalInterface
interface ReturnNoParam {
    public int method();
}
//有返回值有一个参数的函数接口
@FunctionalInterface
interface ReturnOneParam {
    public int method(int a);
}
//有返回值有两个参数的函数接口
@FunctionalInterface
interface ReturnManyParam {
    public int method(int a, int b);
}
public class Test {
    public static void main(String[] args) {
        //无返回值无参数的函数接口实现,类型就是接口名称,{}表示对抽象方法的具体实现
        NoReturnNoParam noReturnNoParam = () -> {
            System.out.println("noReturnNoParam");
        };
        //调用该方法
        noReturnNoParam.method();
        System.out.println("----------------------");
        //无返回值一个参数的接口实现
        NoReturnOneParam noReturnOneParam = (int a) -> {
            System.out.println("noReturnOneParam"+a);
        };
        //调用该方法
        noReturnOneParam.method(1);
        System.out.println("---------------------");
        //无返回值的两个参数的接口实现
        NoReturnManyParam noReturnManyParam = (int a, int b) -> {
            System.out.println("noReturnManyParam"+a+","+b);
        };
        //调用该方法
        noReturnManyParam.method(1, 2);
        System.out.println("--------------------");
        //有返回值无参数的函数接口实现
        ReturnNoParam returnNoParam = () -> {
            System.out.println("returnNoParam");
            return 123;
        };
        //调用该方法
        int a = returnNoParam.method();
        System.out.println("a="+a);
        System.out.println("---------------------");
        //有返回值有一个参数的函数接口实现
        ReturnOneParam returnOneParam = (int a1) -> {
            System.out.println("returnOneParam"+a1);
            return a1;
        };
        //调用该方法
        int b = returnOneParam.method(1);
        System.out.println("b="+b);
        System.out.println("--------------------");
        //有返回值有两个参数的函数接口实现
        ReturnManyParam returnManyParam = (int a1, int a2) -> a1 + a2;
        // 调用该方法
        int c = returnManyParam.method(1, 2);
        System.out.println("c="+c);
    }
}

a67750a1d74a48d4ba032d6b5aaecd11.png

1.3.2 简化Lambda表达式

1、只有一个参数时小括号可以省略。

2、参数列表中的参数可以写,可以不写。要写都写,

3、当方法体之哟一行代码时,大括号可以省略。

4、方法体中只有一行return时,return可以省略。

package cn.it.bz.Lambda;
//无返回值无参数的函数接口
@FunctionalInterface
interface NoReturnNoParam{
    public void method();
}
//无返回值有一个参数的函数接口
@FunctionalInterface
interface NoReturnOneParam {
    public void method(int a);
}
//无返回值有两个参数的函数接口
@FunctionalInterface
interface NoReturnManyParam {
    public void method(int a, int b);
}
//有返回值的无参数函数接口
@FunctionalInterface
interface ReturnNoParam {
    public int method();
}
//有返回值有一个参数的函数接口
@FunctionalInterface
interface ReturnOneParam {
    public int method(int a);
}
//有返回值有两个参数的函数接口
@FunctionalInterface
interface ReturnManyParam {
    public int method(int a, int b);
}
public class Test {
    public static void main(String[] args) {
        //无返回值无参数的函数接口实现
        //方法体只有一行代码时,{}可以不写。
        NoReturnNoParam noReturnNoParam = () -> System.out.println("noReturnNoParam");;
        //调用该方法
        noReturnNoParam.method();
        System.out.println("----------------------");
        //无返回值一个参数的接口实现
        //当参数只有一个时,()可以不写;方法体只有一行代码时,{}可以不写。
        NoReturnOneParam noReturnOneParam = a-> System.out.println("noReturnOneParam"+a);;
        //调用该方法
        noReturnOneParam.method(1);
        System.out.println("---------------------");
        //无返回值的两个参数的接口实现
        //方法体只有一行代码时,{}可以不写。
        NoReturnManyParam noReturnManyParam = (int a, int b) -> System.out.println("noReturnManyParam"+a+","+b);;
        //调用该方法
        noReturnManyParam.method(1, 2);
        System.out.println("--------------------");
        //有返回值无参数的函数接口实现
        ReturnNoParam returnNoParam = () -> {
            System.out.println("returnNoParam");
            return 123;
        };
        //调用该方法
        int a = returnNoParam.method();
        System.out.println("a="+a);
        System.out.println("---------------------");
        //有返回值有一个参数的函数接口实现
        //当参数只有一个时,()可以不写;
        ReturnOneParam returnOneParam = (int a1) -> {
            System.out.println("returnOneParam"+a1);
            return a1;
        };
        //调用该方法
        int b = returnOneParam.method(1);
        System.out.println("b="+b);
        System.out.println("--------------------");
        //当方法体只有return一行代码时,return可以不写。
        ReturnManyParam returnManyParam = (int a1, int a2) -> a1 + a2;
        // 调用该方法
        int c = returnManyParam.method(1, 2);
        System.out.println("c="+c);
    }
}

1.3.3 Lambda表达式引用方法

有时候我们不是必须使用Lambda的函数体定义实现,我们可以利用 lambda表达式指向一个已经存在的方法作为抽象方法的实现。

要求

  • 参数的个数以及类型需要与函数接口中的抽象方法一致。
  • 返回值类型要与函数接口中的抽象方法的返回值类型一致。

语法

方法归属者::方法名 静态方法的归属者为类名,非静态方法归属者为该对象的引用。

package cn.it.bz.Lambda;
@FunctionalInterface
interface ReturnOne {
    public int method(int a);
}
public class Test2 {
    //静态方法
    public static int doubleNumber(int a){ return a*2; }
    //非静态方法
    public int doubleNumber2(int a) {return a * 2;}
    public static void main(String[] args) {
        //将静态方法作为接口中抽象方法的实现方法(前提是参数个数和参数类型必须相同)
        //Test2::doubleNumber表示抽象方法的实现方法是Test类下的doubleNumber方法
        ReturnOne returnOne1 = Test2::doubleNumber;
        //调用
        int method = returnOne1.method(10);
        System.out.println(method);
        //将非静态方法作为接口中抽象方法的实现方法
        //先实例化非静态方法的归属者,通过对象引用实现
        Test2 test2 = new Test2();
        ReturnOne returnOne2 = test2::doubleNumber2;
        int method1 = returnOne1.method(20);
        System.out.println(method1);
    }
}

1.3.4 创建线程

package cn.it.bz.Lambda;
//Runnable接口中只有一个抽象方法run,也就是说Runnable是个函数接口。
public class Test3 {
    public static void main(String[] args) {
        System.out.println("主线程"+ Thread.currentThread().getName()+"启动!");
        //Lambda表达式实现run 方法。
        Runnable runnable = () -> {
            for (int i = 0; i < 10; i++ ) {
                System.out.println(Thread.currentThread().getName() + ", "+i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }
        };
        //线程包装
        Thread thread = new Thread(runnable, "Lambda线程");
        //线程启动
        thread.start();
        System.out.println("主线程"+ Thread.currentThread().getName()+"结束!");
    }
}
 //或者直接将run方法的实现放在Thread构造方法中。
        new Thread(() -> {
            for (int i = 0; i < 10; i++ ) {
                System.out.println(Thread.currentThread().getName() + ", "+i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }
        }, "Lambda线程").start();

5044718b65894122bf53b73c04658338.png

相关文章
|
23天前
|
Java 程序员 API
解锁Java新纪元:Lambda表达式——让你的代码秒变高大上,函数式编程不再是梦!
【8月更文挑战第25天】Java 8 推出了革命性的 Lambda 表达式特性,这是一种匿名函数形式,支持任意数量参数及返回值,简化了代码编写。其基本语法为 `(parameters) -&gt; expression` 或 `(parameters) -&gt; { statements; }`。例如,遍历集合可从使用匿名内部类变为简洁的 `names.forEach(name -&gt; System.out.println(name))`。
36 0
|
18天前
|
并行计算 Java 大数据
Java函数式编程:一场编程范式的革命,让你的代码焕发新生!
【8月更文挑战第30天】Java函数式编程是一种基于数学函数理论的编程范式,强调数据处理的不可变性和纯函数使用,通过将函数视为第一类对象,实现更简洁、易读的代码结构,在数据流处理与并行计算中尤为突出。与命令式编程关注执行步骤不同,函数式编程侧重描述计算目标而非具体操作流程,减少了状态变化,使代码更清晰易维护。在Java中,函数式编程通过降低副作用和状态依赖简化了复杂度,并提高了代码质量和测试性,尤其是在Java 8的Stream API中得到了充分体现,能够自动优化多核处理器上的并行处理性能。
30 2
|
29天前
|
分布式计算 Java API
Java 8带来了流处理与函数式编程等新特性,极大提升了开发效率
Java 8带来了流处理与函数式编程等新特性,极大提升了开发效率。流处理采用声明式编程模型,通过filter、map等操作简化数据集处理,提高代码可读性。Lambda表达式支持轻量级函数定义,配合Predicate、Function等接口,使函数式编程无缝融入Java。此外,Optional类及新日期时间API等增强功能,让开发者能更优雅地处理潜在错误,编写出更健壮的应用程序。
24 1
|
1月前
|
Java API 开发者
Java的变革风暴:Lambda表达式与函数式编程如何颠覆你的代码世界
【8月更文挑战第7天】Java 8引入了Lambda表达式和函数式编程,显著增强了代码的简洁性和可读性。Lambda表达式作为匿名函数,简化了集合操作和事件处理等场景。其基本语法包括参数、箭头及表达式主体。结合Java 8的Stream API,开发者能以声明式风格处理数据,如筛选和转换集合,无需显式循环或条件判断,使得代码更清晰、高效。这些新特性丰富了Java的编程模型,提升了开发效率,并有助于代码的维护。
31 1
|
1月前
|
并行计算 Java 程序员
Java中的Lambda表达式和函数式编程简介
【8月更文挑战第1天】Lambda表达式,在Java 8中引入,为Java程序员提供了一种简洁、灵活的编写代码的方式。本文将通过实例介绍Lambda表达式及其在函数式编程中的应用,并展示如何利用这些特性简化代码和提高开发效率。
18 2
|
2月前
|
Java API 开发者
Java中的Lambda表达式与函数式编程
【7月更文挑战第30天】在Java的世界中,Lambda表达式的引入不仅简化了代码编写,还为开发者打开了函数式编程的大门。本文将探索Lambda表达式的本质、优势以及如何利用它们实现更加简洁和高效的函数式编程范式。
16 3
|
2月前
|
Java API 开发者
探索Java中的Lambda表达式与函数式编程
本文旨在深入探讨Java中Lambda表达式的概念、语法结构及其在函数式编程中的应用。通过对比传统编程模式,展示Lambda表达式如何简化代码、提高开发效率,并结合实例分析其在实际项目开发中的运用。文章还将讨论Lambda表达式的性能考量和在并发编程场景下的优势。
|
2月前
|
Java
Java进阶之函数式编程
Java进阶之函数式编程
25 3
|
2月前
|
Java API 开发者
Java中的Lambda表达式与函数式编程
【7月更文挑战第8天】在探索Java的现代编程范式时,Lambda表达式和函数式编程的概念不断涌现。本文将深入探讨Lambda表达式如何简化代码、提升可读性,并展示其在Java 8及以上版本中实现函数式编程的关键作用。我们将通过实例分析Lambda表达式的语法结构,讨论其在集合操作、线程处理等方面的应用,并对比传统匿名类的方式,揭示Lambda表达式带来的编程效率革命。最后,我们将展望未来函数式编程在Java语言发展中的潜在影响。