一、例子
在Java中,Lambda表达式表达了函数式接口的实例(具有单个抽象方法的接口称为函数式接口)。Java 中的 Lambda 表达式与 lambda 函数相同,接受输入作为参数并返回结果值的短代码块。Lambda 表达式最近包含在 Java SE 8 中。
Java Lambda 表达式的功能
Lambda 表达式实现唯一的抽象函数,因此实现了 Java 8 中添加的功能接口 Lambda 表达式并提供以下功能。
允许将功能视为方法参数,或将代码视为数据。
可以创建不属于任何类的函数。
lambda 表达式可以像对象一样传递并按需执行。
Java Lambda 表达式示例
// Java program to demonstrate lambda expressions
// to implement a user defined functional interface.
// A sample functional interface (An interface with
// single abstract method
interface FuncInterface
{
// An abstract function
void abstractFun(int x);
// A non-abstract (or default) function
default void normalFun()
{
System.out.println("Hello");
}
}
class Test
{
public static void main(String args[])
{
// lambda expression to implement above
// functional interface. This interface
// by default implements abstractFun()
FuncInterface fobj = (int x)->System.out.println(2*x);
// This calls above lambda expression and prints 10.
fobj.abstractFun(5);
}
}
二、Lambda 表达式语法
lambda 运算符 -> 主体
Lambda 表达式参数
下面提到了三个 Lambda 表达式参数:
零参数
单参数
多个参数
- 零参数的 Lambda 表达式
() -> System.out.println(“零参数 lambda”); - 单参数 Lambda 表达式
§ -> System.out.println(“一个参数:” + p);
如果可以从上下文推断该变量的类型,则不强制使用括号
// A Java program to demonstrate simple lambda expressions
import java.util.ArrayList;
class Test {
public static void main(String args[])
{
// Creating an ArrayList with elements
// {1, 2, 3, 4}
ArrayList<Integer> arrL = new ArrayList<Integer>();
arrL.add(1);
arrL.add(2);
arrL.add(3);
arrL.add(4);
// Using lambda expression to print all elements
// of arrL
arrL.forEach(n -> System.out.println(n));
// Using lambda expression to print even elements
// of arrL
arrL.forEach(n -> {
if (n % 2 == 0)
System.out.println(n);
});
}
}
lambda 表达式只能用于实现函数式接口。在上面的示例中,lambda 表达式也实现了消费者功能接口。
3. 多参数Lambda表达式
(p1, p2) -> System.out.println(“多个参数:” + p1 + ", " + p2);
// Java program to demonstrate working of lambda expressions
public class Test {
// operation is implemented using lambda expressions
interface FuncInter1 {
int operation(int a, int b);
}
// sayMessage() is implemented using lambda expressions
// above
interface FuncInter2 {
void sayMessage(String message);
}
// Performs FuncInter1's operation on 'a' and 'b'
private int operate(int a, int b, FuncInter1 fobj)
{
return fobj.operation(a, b);
}
public static void main(String args[])
{
// lambda expression for addition for two parameters
// data type for x and y is optional.
// This expression implements 'FuncInter1' interface
FuncInter1 add = (int x, int y) -> x + y;
// lambda expression multiplication for two
// parameters This expression also implements
// 'FuncInter1' interface
FuncInter1 multiply = (int x, int y) -> x * y;
// Creating an object of Test to call operate using
// different implementations using lambda
// Expressions
Test tobj = new Test();
// Add two numbers using lambda expression
System.out.println("Addition is "
+ tobj.operate(6, 3, add));
// Multiply two numbers using lambda expression
System.out.println("Multiplication is "
+ tobj.operate(6, 3, multiply));
// lambda expression for single parameter
// This expression implements 'FuncInter2' interface
FuncInter2 fobj = message
-> System.out.println("Hello " + message);
fobj.sayMessage("Geek");
}
}
三、集合的 Java Lambda 表达式
import java.util.*;
public class Demo {
public static void main(String[] args)
{
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(205);
al.add(102);
al.add(98);
al.add(275);
al.add(203);
System.out.println("Elements of the ArrayList " +
"before sorting : " + al);
// using lambda expression in place of comparator object
Collections.sort(al, (o1, o2) -> (o1 > o2) ? -1 :
(o1 < o2) ? 1 : 0);
System.out.println("Elements of the ArrayList after" +
" sorting : " + al);
}
}
import java.util.*;
public class Demo {
public static void main(String[] args)
{
TreeMap<Integer, String> m =
new TreeMap<Integer, String>((o1, o2) -> (o1 > o2) ?
-1 : (o1 < o2) ? 1 : 0);
m.put(1, "Apple");
m.put(4, "Mango");
m.put(5, "Orange");
m.put(2, "Banana");
m.put(3, "Grapes");
System.out.println("Elements of the TreeMap " +
"after sorting are : " + m);
}
}
四、Lambda 表达式变量捕获
// Java Program Illustrating Difference between
// Effectively final and Mutable Local Variables
// Importing input output classes
import java.io.*;
// Interface
interface MyInterface {
// Method inside the interface
void myFunction();
}
// Main class
class GFG {
// Custom initialization
int data = 170;
// Main driver method
public static void main(String[] args)
{
// Creating object of this class
// inside the main() method
GFG gfg = new GFG();
// Creating object of interface
// inside the main() method
MyInterface intFace = () ->
{
System.out.println("Data : " + gfg.data);
gfg.data += 500;
System.out.println("Data : " + gfg.data);
};
intFace.myFunction();
gfg.data += 200;
System.out.println("Data : " + gfg.data);
}
}
五、使用 Lambda 表达式创建线程
public class Test {
public static void main(String[] args)
{
// Creating Lambda expression for run() method in
// functional interface "Runnable"
Runnable myThread = () ->
{
// Used to set custom name to the current thread
Thread.currentThread().setName("myThread");
System.out.println(
Thread.currentThread().getName()
+ " is running");
};
// Instantiating Thread class by passing Runnable
// reference to Thread constructor
Thread run = new Thread(myThread);
// Starting the thread
run.start();
}
}
import java.util.Random;
// This is a random player class with two functionalities
// playGames and playMusic
class RandomPlayer {
public void playGame(String gameName)
throws InterruptedException
{
System.out.println(gameName + " game started");
// Assuming game is being played for 500
// milliseconds
Thread.sleep(500); // this statement may throw
// interrupted exception, so
// throws declaration is added
System.out.println(gameName + " game ended");
}
public void playMusic(String trackName)
throws InterruptedException
{
System.out.println(trackName + " track started");
// Assuming music is being played for 500
// milliseconds
Thread.sleep(500); // this statement may throw
// interrupted exception, so
// throws declaration is added
System.out.println(trackName + " track ended");
}
}
public class Test {
// games and tracks arrays which are being used for
// picking random items
static String[] games
= { "COD", "Prince Of Persia", "GTA-V5",
"Valorant", "FIFA 22", "Fortnite" };
static String[] tracks
= { "Believer", "Cradles", "Taki Taki", "Sorry",
"Let Me Love You" };
public static void main(String[] args)
{
RandomPlayer player
= new RandomPlayer(); // Instance of
// RandomPlayer to access
// its functionalities
// Random class for choosing random items from above
// arrays
Random random = new Random();
// Creating two lambda expressions for runnable
// interfaces
Runnable gameRunner = () ->
{
try {
player.playGame(games[random.nextInt(
games.length)]); // Choosing game track
// for playing
}
catch (InterruptedException e) {
e.getMessage();
}
};
Runnable musicPlayer = () ->
{
try {
player.playMusic(tracks[random.nextInt(
tracks.length)]); // Choosing random
// music track for
// playing
}
catch (InterruptedException e) {
e.getMessage();
}
};
// Instantiating two thread classes with runnable
// references
Thread game = new Thread(gameRunner);
Thread music = new Thread(musicPlayer);
// Starting two different threads
game.start();
music.start();
/*
*Note: As we are dealing with threads output may
*differ every single time we run the program
*/
}
}
六、Lambda表达式的序列化
// Java Program to serialize and deserialize the lambda
// function using a function interface
// Importing input output classes
import java.io.*;
// Importing all function utility classes
import java.util.function.*;
// Interface
interface MyInterface {
// Method inside this interface
void hello(String name);
}
// Class 1
// Helper class implementing above interface
class MyImpl implements MyInterface {
// Method of this class
public void hello(String name)
{
System.out.println("Hello " + name);
}
}
// Class 2
// Main class
class GFG {
// Method 1
// To Serialize
private static void serialize(Serializable obj,
String outputPath)
throws IOException
{
File outputFile = new File(outputPath);
if (!outputFile.exists()) {
outputFile.createNewFile();
}
try (ObjectOutputStream outputStream
= new ObjectOutputStream(
new FileOutputStream(outputFile))) {
outputStream.writeObject(obj);
}
}
// Method 2
// To Deserialize
private static Object deserialize(String inputPath)
throws IOException, ClassNotFoundException
{
File inputFile = new File(inputPath);
try (ObjectInputStream inputStream
= new ObjectInputStream(
new FileInputStream(inputFile))) {
return inputStream.readObject();
}
}
// Method 3
// To Serialize and deserialize lambda functions
private static void serializeAndDeserializeFunction()
throws Exception
{
Function<Integer, String> fn
= (Function<Integer, String> & Serializable)(n)
-> "Hello " + n;
System.out.println("Run original function: "
+ fn.apply(10));
String path = "./serialized-fn";
serialize((Serializable)fn, path);
System.out.println("Serialized function to "
+ path);
Function<Integer, String> deserializedFn
= (Function<Integer, String>)deserialize(path);
System.out.println("Deserialized function from "
+ path);
System.out.println("Run deserialized function: "
+ deserializedFn.apply(11));
}
// Method 4
// To Serialize and deserialize lambda classes
private static void serializeAndDeserializeClass()
throws Exception
{
String path = "./serialized-class";
serialize(MyImpl.class, path);
System.out.println("Serialized class to " + path);
// Pretending we don't know the exact class of the
// serialized bits, create an instance from the
// class and use it through the interface.
Class<?> myImplClass = (Class<?>)deserialize(path);
System.out.println("Deserialized class from "
+ path);
MyInterface instance
= (MyInterface)myImplClass.newInstance();
instance.hello("Java");
}
// Method 5
// Main driver method
public static void main(String[] args) throws Exception
{
// Calling above method 3 and method 4
// in the main() body
serializeAndDeserializeFunction();
serializeAndDeserializeClass();
}
}
七、块 Lambda 表达式
Lambda 表达式是一个未命名的方法,不会自行执行。这些表达式导致匿名类。这些 lambda 表达式称为闭包。Lambda 的主体由一段代码组成。如果它只有一个表达式,则称为“表达式体”。包含表达式体的 Lambda 称为“表达式 Lambda ”。下面是单行 Lambda 表达式的示例。
Block Lambda 包含许多适用于 lambda 表达式的操作,因为它允许 lambda 主体包含许多语句。这包括变量、循环、条件语句(如 if、else 和 switch 语句)、嵌套块等。这是通过将 lambda 主体中的语句块括在大括号 {} 中来创建的。这甚至可以有一个返回语句,即返回值。
语法: Lambda 表达式
(参数)-> { lambda 体 }
// Java Program to illustrate Block Lambda expression
// Importing all classes from
// java.util package
import java.io.*;
// Block lambda to find out factorial
// of a number
// Interface
interface Func {
// n is some natural number whose
// factorial is to be computed
int fact(int n);
}
// Class
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Block lambda expression
Func f = (n) ->
{
// Block body
// Initially initializing with 1
int res = 1;
// iterating from 1 to the current number
// to find factorial by multiplication
for (int i = 1; i <= n; i++)
res = i * res;
return res;
};
// Calling lambda function
// Print and display n the console
System.out.println("Factorial of 5 : " + f.fact(5));
}
}
八、将 Lambda 与 Java 中的接口相匹配
从java中的接口开始,接口是类似于类的引用类型,但仅包含抽象方法。这是java 1.8之前我们对接口的定义。与java 1.8版本之前一样,我们使用任何版本,接口分为以下三种类型:
普通界面
与多种方法的接口。
标记接口(接口不包含任何方法)。
从 1.8 开始,所有 SAM(单一抽象方法)接口都称为功能接口。
函数式接口:函数式接口是一种仅包含一个抽象方法的接口,但重要的是要记住它可以具有任意数量的默认或静态方法以及对象类方法,因为这最让程序员感到困惑。
// Java Program to Illustrate Lambda Expression
// with Multiple Parameter
// Importing required classes
import java.util.*;
// Main class
class GFG {
// main driver method
public static void main(String[] args)
{
// Creating a List of integer type
List<Integer> list
= Arrays.asList(24, 346, 78, 90, 21, 765);
// Printing before sorting
System.out.println("Before sorting.");
for (int i : list)
System.out.print(i + " ");
System.out.println();
// Sort the integers based on second digit
Collections.sort(list, (a1, a2) -> {
return a1 % 10 > a2 % 10 ? 1 : -1;
});
// Printing after sorting
System.out.println("After sorting.");
for (int i : list)
System.out.print(i + " ");
System.out.println();
}
}
九、使用 Lambda 表达式将 ArrayList 转换为 HashMap
lambda 表达式是一行或多行代码,其工作方式类似于函数或方法。它接受一个参数并返回值。Lambda 表达式可用于将 ArrayList 转换为 HashMap。
句法:
(parms1, parms2) -> 表达式
// Converting ArrayList to HashMap
// in Java 8 using a Lambda Expression
import java.util.*;
import java.util.ArrayList;
import java.util.Scanner;
// here we are making a class , and we will make
class ListItems {
// key will act as an id of the value
private Integer key;
// value will be the value of the above key
private String value;
// create constructor for reference
public ListItems(Integer id, String name)
{
// assigning the value of key and value
this.key = id;
this.value = name;
}
// return private variable key
public Integer getkey() { return key; }
// return private variable name
public String getvalue() { return value; }
}
class Main {
public static void main(String[] args)
{
// Write your code here
// Creating a List of type ListItems using ArrayList
List<ListItems> list = new ArrayList<ListItems>();
// add the member of list
list.add(new ListItems(1, "I"));
list.add(new ListItems(2, "Love"));
list.add(new ListItems(3, "Geeks"));
list.add(new ListItems(4, "For"));
list.add(new ListItems(5, "Geeks"));
// Map which will store the list items
Map<Integer, String> map = new HashMap<>();
// for (ListItems n : list) { map.put(n.getkey(),
// n.getvalue()); }
// the below lambda performs the same task as the
// above given for loop will do
// put the list items in the Map
list.forEach(
(n) -> { map.put(n.getkey(), n.getvalue()); });
// Printing the given map
System.out.println("Map : " + map);
}
}