Lambda 语法
Lambda 表达式语法
(Parameters) -> {Body}
,参数用括号括起来,这和方法的方法是一样的,而
显示与隐式声明
参数
一个没有声明其参数类型的
public class Main {
public static void main(String[] args) {
// 显式
MyIntegerCalculator myIntegerCalculator = (Integer s1) -> s1 * 2;
// 隐式
MyIntegerCalculator myIntegerCalculator = (s1) -> s1 * 2;
System.out.println("1- Result x2 : " + myIntegerCalculator.calcIt(5));
}
}
interface MyIntegerCalculator {
public Integer calcIt(Integer s1);
}
我们可以选择省略
public class Main {
public static void main(String[] argv) {
Processor stringProcessor = (str) -> str.length();
String name = "Java Lambda";
int length = stringProcessor.getStringLength(name);
System.out.println(length);//from ww w.ja v a 2 s . c om
}
}
@FunctionalInterface
interface Processor {
int getStringLength(String str);
}
对于单参数
public class Main {
public static void main(String[] argv) {
Processor stringProcessor = str -> str.length();
String name = "Java Lambda";
int length = stringProcessor.getStringLength(name);
System.out.println(length);/* w w w. jav a2s .c o m*/
}
}
@FunctionalInterface
interface Processor {
int getStringLength(String str);
}
对于一个没有参数的
import java.util.function.BooleanSupplier;
public class Main {
public static void main(String[] args) {
BooleanSupplier bs = () -> true;
System.out.println(bs.getAsBoolean());
int x = 0, y= 1;
bs = () -> x > y;
System.out.println(bs.getAsBoolean());
}
}
你可以在参数声明中使用
public class Main {
public static void main(String[] argv) {
Processor stringProcessor = (final String str) -> str.length();
String name = "Java Lambda";
int length = stringProcessor.getStringLength(name);
System.out.println(length);/* w w w . ja v a 2s .co m*/
}
}
@FunctionalInterface
interface Processor {
int getStringLength(String str);
}
函数体
(String msg)->{System.out.println(msg);}// a block statement
(String msg)->System.out.println(msg) //an expression
public class Main {
public static void main(String[] argv) {
Processor stringProcessor = (String str) -> str.length();
String name = "Java Lambda";
int length = stringProcessor.getStringLength(name);
System.out.println(length);// www . j a va 2 s. co m
}
}
@FunctionalInterface
interface Processor {
int getStringLength(String str);
}
类型推导
一个
public class Main {
public static void main(String[] argv) {
Processor stringProcessor = (String str) -> str.length();
SecondProcessor secondProcessor = (String str) -> str.length();
//stringProcessor = secondProcessor; //compile error
String name = "Java Lambda";
int length = stringProcessor.getStringLength(name);
System.out.println(length);
}
}
@FunctionalInterface
interface Processor {
int getStringLength(String str);
}
@FunctionalInterface
interface SecondProcessor {
int noName(String str);
}
- 它必须是一个函数接口
Lambda 表达式的参数必须与函数式接口中的抽象方法相匹配。Lambda 表达式的返回类型与函数式接口中的抽象方法的返回类型兼容。- 从
Lambda 表达式中抛出的检查异常必须与函数式接口中抽象方法的声明的throws 子句兼容。
编译器并不总是能够推断出
public class Main {
public static void main(String[] argv) {
// 指明参数
engine((IntCalculator) ((x,y)-> x + y));
// 指明类型
IntCalculator iCal = (x,y)-> x + y;
engine((int x,int y)-> x + y);
engine((long x, long y)-> x * y);
engine((int x,int y)-> x / y);
engine((long x,long y)-> x % y);
}
private static void engine(IntCalculator calculator){
int x = 2, y = 4;
int result = calculator.calculate(x,y);
System.out.println(result);
}
private static void engine(LongCalculator calculator){
long x = 2, y = 4;
long result = calculator.calculate(x,y);
System.out.println(result);
}
}
@FunctionalInterface
interface IntCalculator{
int calculate(int x, int y);
}
@FunctionalInterface
interface LongCalculator{
long calculate(long x, long y);
}
方法引用
一个Qualifier::MethodName
两个连续的冒号作为分隔符。
TypeName::staticMethod: 类、接口或枚举的静态方法的引用。objectRef::instanceMethod: 对实例方法的引用ClassName::instanceMethod: 引用类的实例方法TypeName.super::instanceMethod: 从对象的超类型中引用一个实例方法。ClassName::new: 类的构造函数的引用ArrayTypeName::new: 引用指定数组类型的构造函数。
Static Method References
静态方法引用允许我们使用静态方法作为
import java.util.function.Function;
public class Main {
public static void main(String[] argv) {
// Using a lambda expression
Function<Integer, String> func1 = x -> Integer.toBinaryString(x);
System.out.println(func1.apply(10));
// Using a method reference
Function<Integer, String> func2 = Integer::toBinaryString;
System.out.println(func2.apply(10));
}
}
我们可以在静态方法引用中使用重载静态方法。在重载方法的时候我们要多注意方法的签名和对应的功能接口。在下面的列表中,我们有三个版本的来自
static Integer valueOf(int i)
static Integer valueOf(String s)
static Integer valueOf(String s, int radix)
下面的代码显示了不同的目标功能接口如何与重载的
import java.util.function.BiFunction;
import java.util.function.Function;
public class Main{
public static void main(String[] argv){
// Uses Integer.valueOf(int)
Function<Integer, Integer> func1 = Integer::valueOf;
// Uses Integer.valueOf(String)
Function<String, Integer> func2 = Integer::valueOf;
// Uses Integer.valueOf(String, int)
BiFunction<String, Integer, Integer> func3 = Integer::valueOf;
System.out.println(func1.apply(7));
System.out.println(func2.apply("7"));
System.out.println(func3.apply("101010101010", 2));
}
}
实例方法引用
我们可以通过两种方式获取实例方法引用,从对象实例或从类名中获取。基本上我们有以下两种形式:instance::MethodName, ClassName::MethodName。这里的instance
和instance
被称为有界接受者,而instance
为有界接受者,因为接受者与 instance
是有界的,而
Bound Instance Method Reference
在他们下面的代码中,我们使用构建系统功能接口
import java.util.function.Supplier;
public class Main{
public static void main(String[] argv){
Supplier<Integer> supplier = () -> "test".length();
System.out.println(supplier.get());
Supplier<Integer> supplier1 = "test"::length;
System.out.println(supplier1.get());
}
}
下面的例子展示了如何使用绑定接收器和带参数的方法来创建实例方法引用。
import java.util.function.Consumer;
public class Main{
public static void main(String[] argv){
Util util = new Util();
Consumer<String> consumer = str -> util.print(str);
consumer.accept("Hello");
Consumer<String> consumer1 = util::print;
consumer1.accept("test");
util.debug();
}
}
class Util{
private int count=0;
public void print(String s){
System.out.println(s);
count++;
}
public void debug(){
System.out.println("count:" + count);
}
}
Unbound Instance Method Reference
一个未绑定的接收器使用以下语法:ClassName::instanceMethod
,这与我们用来引用静态方法的语法相同。从下面的代码中我们可以看到,输入类型是String:length
,所以功能接口的输入类型是
import java.util.function.Function;
public class Main{
public static void main(String[] argv){
Function<String, Integer> strLengthFunc = String::length;
String name ="test";
int len = strLengthFunc.apply(name);
System.out.println("name = " + name + ", length = " + len);
name ="testtest";
len = strLengthFunc.apply(name);
System.out.println("name = " + name + ", length = " + len);
}
}
下面的代码定义了一个带有静态方法
import java.util.function.BiFunction;
public class Main{
public static void main(String[] argv){
BiFunction<String, String, String> strFunc = Util::append;
String name = "test";
String s = strFunc.apply(name, "hi");
System.out.println(s);
}
}
class Util{
public static String append(String s1,String s2){
return s1+s2;
}
}
Supertype Instance Method References
关键字ClassName.super::instanceMethod
。下面的代码定义了一个名为
然后创建了一个名为
import java.util.function.BiFunction;
public class Main{
public static void main(String[] argv){
new Util();
}
}
class Util extends ParentUtil{
public Util(){
BiFunction<String, String,String> strFunc = this::append;
String name = "test";
String s = strFunc.apply(name," hi");
System.out.println(s);
strFunc = Util.super::append;
name ="test";
s = strFunc.apply(name," Java Lambda Tutorial");
System.out.println(s);
}
@Override
public String append(String s1,String s2){
System.out.println("child append");
return s1+s2;
}
}
class ParentUtil{
public String append(String s1,String s2){
System.out.println("parent append");
return s1+s2;
}
}
Constructor Reference
我们可以使用构造函数来创建一个ClassName::new
。关键字
import java.util.function.Function;
import java.util.function.Supplier;
public class Main{
public static void main(String[] argv){
Supplier<String> func1 = () -> new String();
System.out.println("Empty String:"+func1.get());
Function<String,String> func2 = str -> new String(str);
System.out.println(func2.apply("test"));
Supplier<String> func3 = String::new;
System.out.println("Empty String:" + func3.get());
Function<String,String> func4 = String::new;
System.out.println(func4.apply("test"));
}
}
Array Constructor References
我们可以使用数组构造函数创建一个数组,如下所示:ArrayTypeName::new。
import java.util.Arrays;
import java.util.function.IntFunction;
public class Main{
public static void main(String[] argv){
IntFunction<int[]> arrayCreator1 = size -> new int[size];
// Creates an int array of five elements
int[] intArray1 = arrayCreator1.apply(5);
System.out.println(Arrays.toString(intArray1));
IntFunction<int[]> arrayCreator2 = int[]::new;
int[] intArray2 = arrayCreator2.apply(5);
System.out.println(Arrays.toString(intArray2));
}
}
通过使用 Function<Integer,ArrayType>
,我们可以在声明中指定数组类型。
import java.util.Arrays;
import java.util.function.Function;
public class Main{
public static void main(String[] argv){
Function<Integer, int[]> arrayCreator3 = int[]::new;
int[] intArray = arrayCreator3.apply(5);
System.out.println(Arrays.toString(intArray));
}
}
在创建二维数组时,我们可以指定第一维的长度。
import java.util.Arrays;
import java.util.function.IntFunction;
public class Main{
public static void main(String[] argv){
IntFunction<int[][]> TwoDimArrayCreator = int[][]::new;
int[][] intArray = TwoDimArrayCreator.apply(5);
// Creates an int[5][] array
intArray[0] = new int[5];
intArray[1] = new int[5];
intArray[2] = new int[5];
intArray[3] = new int[5];
intArray[4] = new int[5];
System.out.println(Arrays.deepToString(intArray));
}
}
Generic Method Reference
我们可以在方法引用中通过指定实际类型参数来使用通用方法。其语法如下:ClassName::<TypeName>methodName
,通用构造函数引用的语法:ClassName<TypeName>::new
。
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class Main{
public static void main(String[] argv){
Function<String[],List<String>> asList = Arrays::<String>asList;
System.out.println(asList.apply(new String[]{"a","b","c"}));
}
}