Java函數(shù)式Lambda編程的使用學(xué)習(xí)(圖文教程)
函數(shù)式編程指的是使用Lambda函數(shù)替代某些匿名內(nèi)部類,從而讓程序代碼更簡(jiǎn)潔,可讀性更好
1.Lambda表達(dá)式
1.1 定義
- JDK 8開始新增的一種語(yǔ)法形式,它表示函數(shù)
- 可以用于替代某些匿名內(nèi)部類,從而讓程序更簡(jiǎn)潔,可讀性更好
Tips:Lambda表達(dá)式只能替代函數(shù)式接口的匿名內(nèi)部類
(被重寫方法的形參列表)->
{
被重寫方法的方法體代碼
}
函數(shù)式接口:
- 有且僅有一個(gè)抽象方法的接口
- 注意:將來(lái)見到的大部分函數(shù)式接口,上面都可能會(huì)有一個(gè)@FunctionalInterface的注解,該注解用于約束當(dāng)前接口必須是函數(shù)式接口
public class Lambdademo {
public static void main(String[] args) {
Animal a = new Animal() {
@Override
public void eat() {
System.out.println("狗吃骨頭");
}
};
a.eat();
System.out.println("============================");
Swim s1=new Swim() {
@Override
public void swim() {
System.out.println("學(xué)生游泳賊快");
}
}
Swim s2=()->{
System.out.println("學(xué)生游泳賊快");
}
}
}
abstract class Animal{
abstract void eat();
}
//函數(shù)式接口:有且僅有一個(gè)抽象方法的接口
@FunctionalInterface//聲明函數(shù)式接口的注解
interface Swim{
void swim();
}
分析這段代碼:
Animal由于只是抽象類不是接口,所以不能使用Lambda表達(dá)式替代
而Swim是接口,且只有一個(gè)抽象方法所以能被Lambda表達(dá)式替代
**為什么這個(gè)Lambda能替代?**因?yàn)槟芡茢喑錾舷挛?,Swim s2能推斷出是一個(gè)接口,后面的方法體代碼能代碼能推斷出只有一個(gè)抽象方法,所以能推斷出原來(lái)的代碼如s1。
1.2 實(shí)例
1.2.1 用comparator接口的匿名內(nèi)部函數(shù)類實(shí)現(xiàn)對(duì)數(shù)組進(jìn)行排序
在匿名內(nèi)部類中使用comparator接口的匿名內(nèi)部函數(shù)類實(shí)現(xiàn)對(duì)數(shù)組進(jìn)行排序代碼中可以看到編譯器用灰色標(biāo)記Comparator提示可以進(jìn)行Lambda表達(dá)式進(jìn)行簡(jiǎn)化,進(jìn)入該方法的聲明,該方法有聲明函數(shù)式接口的注解,說(shuō)明該匿名內(nèi)部類可以使用Lambda表達(dá)式進(jìn)行化簡(jiǎn)
import com.fqw.anonymousclass.Student;
import java.util.Arrays;
import java.util.Comparator;
public class Lambdademo1 {
public static void main(String[] args) {
Student[] students=new Student[6];
students[0]=new Student("張三", 18, 1.75);
students[1]=new Student("李四", 23, 1.80);
students[2]=new Student("王五", 20, 1.65);
students[3]=new Student("趙六", 17, 1.70);
students[4]=new Student("錢七", 22, 1.65);
students[5]=new Student("孫八", 16, 1.75);
//輸出排序前的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2)
{
return o1.getAge()-o2.getAge();//升序
}
});
System.out.println("=======================================");
//輸出排序后的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
}
}


簡(jiǎn)化后的代碼
import com.fqw.anonymousclass.Student;
import java.util.Arrays;
import java.util.Comparator;
public class Lambdademo1 {
public static void main(String[] args) {
Student[] students=new Student[6];
students[0]=new Student("張三", 18, 1.75);
students[1]=new Student("李四", 23, 1.80);
students[2]=new Student("王五", 20, 1.65);
students[3]=new Student("趙六", 17, 1.70);
students[4]=new Student("錢七", 22, 1.65);
students[5]=new Student("孫八", 16, 1.75);
//輸出排序前的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
Arrays.sort(students, (Student o1, Student o2)->{
return o1.getAge()-o2.getAge();//升序
});
System.out.println("=======================================");
//輸出排序后的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
}
}
1.2.2 登錄窗口登錄
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Lambdademo2 {
public static void main(String[] args) {
//需求:創(chuàng)建一個(gè)登錄窗口,登錄窗口中包含一個(gè)登錄按鈕
JFrame win = new JFrame("登錄窗口");
win.setSize(300, 200);
win.setLocationRelativeTo(null);//居中顯示
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//創(chuàng)建一個(gè)面板,把按鈕添加到面板中
JPanel panel = new JPanel();
win.add(panel);
//創(chuàng)建一個(gè)按鈕
JButton button = new JButton("登錄");
panel.add(button);
//java要求必須給按鈕添加一個(gè)點(diǎn)擊事件監(jiān)聽器對(duì)象,這樣就可以監(jiān)聽用戶事件,做出反應(yīng)
button.addActionListener((ActionEvent e) -> {
System.out.println("登錄成功");
});
win.setVisible(true);
}
}
1.3 省略規(guī)則(進(jìn)一步簡(jiǎn)化Lambda表達(dá)式的寫法)
- 參數(shù)類型全部可以省略不寫
- 如果只有一個(gè)參數(shù),參數(shù)類型省略的同時(shí)“()”也可以省略,但多個(gè)參數(shù)不能省略“()”
- 如果Lambda表達(dá)式只有一行代碼,大括號(hào)可以不寫,同時(shí)要省略分號(hào)”;”,如果這行代碼是return語(yǔ)句,也必須去掉return
根據(jù)簡(jiǎn)化規(guī)則簡(jiǎn)化后的代碼:
import com.fqw.anonymousclass.Student;
import java.util.Arrays;
import java.util.Comparator;
public class Lambdademo1 {
public static void main(String[] args) {
Student[] students=new Student[6];
students[0]=new Student("張三", 18, 1.75);
students[1]=new Student("李四", 23, 1.80);
students[2]=new Student("王五", 20, 1.65);
students[3]=new Student("趙六", 17, 1.70);
students[4]=new Student("錢七", 22, 1.65);
students[5]=new Student("孫八", 16, 1.75);
//輸出排序前的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
Arrays.sort(students, ( o1, o2) -> o1.getAge()-o2.getAge());
System.out.println("=======================================");
//輸出排序后的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
}
}
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Lambdademo2 {
public static void main(String[] args) {
//需求:創(chuàng)建一個(gè)登錄窗口,登錄窗口中包含一個(gè)登錄按鈕
JFrame win = new JFrame("登錄窗口");
win.setSize(300, 200);
win.setLocationRelativeTo(null);//居中顯示
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//創(chuàng)建一個(gè)面板,把按鈕添加到面板中
JPanel panel = new JPanel();
win.add(panel);
//創(chuàng)建一個(gè)按鈕
JButton button = new JButton("登錄");
panel.add(button);
//java要求必須給按鈕添加一個(gè)點(diǎn)擊事件監(jiān)聽器對(duì)象,這樣就可以監(jiān)聽用戶事件,做出反應(yīng)
button.addActionListener(e -> System.out.println("登錄成功"));
win.setVisible(true);
}
}
2.方法引用(了解)
2.1 靜態(tài)方法引用
類名::靜態(tài)方法
使用場(chǎng)景:如果某個(gè)Lambda表達(dá)式里只調(diào)用一個(gè)靜態(tài)方法,并且“->”前后參數(shù)的形式一致,就可以使用靜態(tài)方法
1.首先,在類中定義一個(gè)靜態(tài)的方法,如學(xué)生類中定義一個(gè)比較年齡的靜態(tài)類
package com.fqw.method1reference;
public class Student {
//姓名、年齡、身高
private String name;
private int age;
private double height;
public Student() {}
public Student(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public static int compareAge(Student s1, Student s2){
return s1.getAge() - s2.getAge();
}
}
2.接著,使用靜態(tài)方法引用
package com.fqw.method1reference;
import java.util.Arrays;
public class Demo1{
public static void main(String[] args) {
Student[] students=new Student[6];
students[0]=new Student("張三", 18, 1.75);
students[1]=new Student("李四", 23, 1.80);
students[2]=new Student("王五", 20, 1.65);
students[3]=new Student("趙六", 17, 1.70);
students[4]=new Student("錢七", 22, 1.65);
students[5]=new Student("孫八", 16, 1.75);
//輸出排序前的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
//Arrays.sort(students, ( o1, o2) -> o1.getAge()-o2.getAge);
//Arrays.sort(students, ( o1, o2) -> Student.compareAge(o1,o2));
//靜態(tài)方法引用 類名::靜態(tài)方法
Arrays.sort(students, Student::compareAge);
System.out.println("=======================================");
//輸出排序后的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
}
}
2.2 實(shí)例方法引用
對(duì)象名::實(shí)例方法
使用場(chǎng)景:如果某個(gè)Lambda表達(dá)式里只是通過(guò)對(duì)象名稱調(diào)用一個(gè)實(shí)例方法,并且“->”前后參數(shù)的形式一致,就可以使用實(shí)例方法
package com.fqw.method1reference;
public class Student {
//姓名、年齡、身高
private String name;
private int age;
private double height;
public Student() {}
public Student(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public int compareByHeight(Student o1,Student o2){
return Double.compare(o1.getHeight(), o2.getHeight());
}
}
package com.fqw.method1reference;
import java.util.Arrays;
public class Demo2 {
public static void main(String[] args) {
Student[] students=new Student[6];
students[0]=new Student("張三", 18, 1.75);
students[1]=new Student("李四", 23, 1.80);
students[2]=new Student("王五", 20, 1.65);
students[3]=new Student("趙六", 17, 1.70);
students[4]=new Student("錢七", 22, 1.65);
students[5]=new Student("孫八", 16, 1.75);
//輸出排序前的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
//實(shí)例方法引用 對(duì)象名::靜態(tài)方法
Student t=new Student();
//Arrays.sort(students, ( o1, o2) -> t.compareByHeight(o1,o2));
Arrays.sort(students, t::compareByHeight);
System.out.println("=======================================");
//輸出排序后的學(xué)生數(shù)組
for (int i=0;i<students.length;i++){
Student student = students[i];
System.out.println(student.getName()+","+ student.getAge()+","+ student.getHeight());
}
}
}
2.3 特定類型方法的引用
特定類的名稱::方法
使用場(chǎng)景:如果某個(gè)Lambda表達(dá)式里只調(diào)用一個(gè)特定類型的實(shí)例方法,并且前面參數(shù)列表中的第一個(gè)參數(shù)是作為方法的主調(diào),后面的所有參數(shù)都是作為該實(shí)例方法的入?yún)⒌?,則此時(shí)就可以使用特定類型的方法引用
場(chǎng)景:有一個(gè)字符串?dāng)?shù)組,里面有一些人的名字,都是英文名字,請(qǐng)按照名字的英文首字母排序,忽略首字母大小
import java.util.Arrays;
import java.util.Comparator;
public class Demo3 {
public static void main(String[] args) {
//有一個(gè)字符串?dāng)?shù)組,里面有一些人的名字,都是英文名字,請(qǐng)按照名字的英文首字母排序,忽略首字母大小
String[] names=new String[]{"Tom","lisi","angela","zhaoliu","Mike","Jack","Bob","Andy","caocao","Rose"};
// Arrays.sort(names, new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.compareToIgnoreCase(o2);
// }
// });
//Arrays.sort(names, (o1,o2)->o1.compareToIgnoreCase(o2));
Arrays.sort(names, String::compareToIgnoreCase);
System.out.println(Arrays.toString(names));
}
}
2.4 構(gòu)造器引用
類名::new
使用場(chǎng)景:如果某個(gè)Lambda表達(dá)式里只是創(chuàng)建對(duì)象,并且“->”前后參數(shù)的形式一致,就可以使用構(gòu)造器引用
package com.fqw.method1reference;
public class Demo4 {
public static void main(String[] args) {
// CarFactory cf=new CarFactory() {
// @Override
// public Car getCar(String name){
// return new Car(name);
// }
// };
// CarFactory cf=name -> new Car(name);
CarFactory cf=Car:: new ;
Car c1=cf.getCar("奧迪");
System.out.println(c1.getName());
}
}
interface CarFactory{
Car getCar(String name);
}
class Car{
private String name;
public Car() {
}
public Car(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
相關(guān)文章
MyBatis Plus更新對(duì)象無(wú)法設(shè)空值解決方案
這篇文章主要介紹了MyBatis Plus更新對(duì)象無(wú)法設(shè)空值解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
java解析xml的4種方式的優(yōu)缺點(diǎn)對(duì)比及實(shí)現(xiàn)詳解
這篇文章主要介紹了java解析xml的4種方式的優(yōu)缺點(diǎn)對(duì)比及實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
mybatis多對(duì)多關(guān)聯(lián)實(shí)戰(zhàn)教程(推薦)
下面小編就為大家?guī)?lái)一篇mybatis多對(duì)多關(guān)聯(lián)實(shí)戰(zhàn)教程(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
教你Springboot如何實(shí)現(xiàn)圖片上傳
這篇文章主要介紹了教你Springboot如何實(shí)現(xiàn)圖片上傳,首先大家明白圖片上傳,需要在數(shù)據(jù)庫(kù)定義一個(gè)varchar類型的img字段圖片字段,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
詳解Java多線程編程中線程的啟動(dòng)、中斷或終止操作
在Java中start和tun方法可用被用來(lái)啟動(dòng)線程,而用interrupt方法來(lái)中斷或終止線程,以下我們就來(lái)詳解Java多線程編程中線程的啟動(dòng)、中斷或終止操作2016-07-07
spring(java,js,html) 截圖上傳圖片實(shí)例詳解
這篇文章主要介紹了spring(java,js,html) 截圖上傳圖片實(shí)例詳解的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07
Java利用SpEL表達(dá)式實(shí)現(xiàn)權(quán)限校驗(yàn)
這篇文章主要為大家詳細(xì)介紹了Java如何利用SpEL表達(dá)式實(shí)現(xiàn)權(quán)限校驗(yàn)功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01

