01-lambda
1. lambda
interface IFactory {
Object getUser();
}
// 接口实现类
class Factory implements IFactory {
@Override
public Object getUser() {
return new User();
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
private String name;
private int age;
}
/*
* Lambda表达式初体验
* 代码更简洁
* 函数式编程:更关注函数/功能,而非对象
* 函数是“第一等公民”
* 1. 可以赋值给变量
* 2. 可以作为(其它函数的)参数进行传递
* 3. 可以作为(其它函数的)返回值
*/
public class T1_Lambda {
/**
* 1. 子类实现接口
*/
@Test
public void T1_subClass() {
IFactory factory = new Factory();
User user = (User) factory.getUser();
System.out.println(user);
}
/**
* 2. 匿名内部类
*/
@Test
public void T2_anonymousClass() {
// shortcut:new IFactory() => opt + Enter
IFactory factory = new IFactory() {
@Override
public Object getUser() {
return new User("张三", 39);
}
};
User user = (User) factory.getUser();
System.out.println(user);
}
/**
* 3. 赋值给变量
* 只关注函数体(入参列表、返回值)
*/
@Test
public void T3_variable() {
IFactory factory = () -> {
return new User("李四", 18);
};
User user = (User) factory.getUser();
System.out.println(user);
// 补充:函数体中,只有简单的表达式语句时,可以省略大括号{}
factory = () -> new User("王五", 20);
user = (User) factory.getUser();
System.out.println(user);
}
/**
* 4. lambda作为实参
*/
@Test
public void T5_param() {
User user = _param(
() -> new User("赵六", 18),
"User"
);
System.out.println(user);
}
public static User _param(IFactory factory, String beanName) {
Object obj = factory.getUser();
// obj.getClass().getSimpleName() 获取简单类名
// obj.getClass().getName() 获取包内路径名
if (obj != null && obj.getClass().getSimpleName().equals(beanName)) {
return (User) obj;
}
return null;
}
/**
* 5. lambda作为返回值
*/
@Test
public void T6_return() {
IFactory factory = _return();
System.out.println(factory.getUser());
}
private static IFactory _return() {
return () -> new User("钱七", 18);
}
}
2. LambdaSyntax
Syntax 英 [ˈsɪntæks] 语法;新泰;句法;句法学;語法
braces 英 [ˈbreɪsɪz] n. 箍子;夹子;支架;(儿童)牙箍;吊裤带;背带
parenthesis 英 [pəˈrenθəsɪs] n. 插入语
brackets 英 [ˈbrækɪts] n. 括号; v. 用括弧括上;
/*
* 语法:
* (parameters) -> { statements; }
* (parameters) -> expression
* -> :使用指定参数去完成某个功能
*
* 前提:必须有一个函数式接口 —— @FunctionalInterface
* Lambda表达式与@FunctionalInterface的抽象函数格式一一对应
*
* @FunctionalInterface
* 1. 有且只有一个抽象方法的接口
*/
public class T2_LambdaSyntax {
/**
* 1. 有且只有一个抽象方法的接口
* 2. 可以有static()
* 3. 可以有default()
*/
@FunctionalInterface
interface IGreeting {
void sayHello(String message);
static void show() {
}
default void get() {
}
}
@FunctionalInterface
interface IMathOper {
int operation(int a, int b);
}
/**
* 0. 基本格式
*/
@Test
public void T1_base() {
IMathOper add = (int a, int b) -> {
return a + b;
};
System.out.println(add.operation(1, 2));
}
/*
* 1. 省略大括号{}
*/
@Test
public void T2_simplify_braces() {
IGreeting greeting = (String msg) -> System.out.println("hello " + msg);
greeting.sayHello("Lambda");
}
/*
* 2. 只有一个参数省略小括号()
*/
@Test
public void T3_simplify_parenthesis() {
IGreeting greeting = msg -> System.out.println("hello " + msg);
greeting.sayHello("ooxx");
}
/**
* 3. 省略return
*/
@Test
public void T4_simplify_return() {
IMathOper mo1 = (int a, int b) -> a + b;
System.out.println(mo1.operation(3, 4));
}
/**
* 4. 省略参数类型
*/
@Test
public void T5_simplify_paramType() {
IMathOper mo2 = (a, b) -> a * b;
System.out.println(mo2.operation(6, 5));
}
}
3. FunctionalInterface
supplier 英 [səˈplaɪə(r)] n. 供应商;供货商;供应者;供货方
negate 英 [nɪˈɡeɪt] vt. 取消;使无效;否定;否认
predicate 英 /ˈpredɪkət , ˈpredɪkeɪt/ v. 使基于;断言;表明;使以…为依据
/**
* 函数式接口
*/
public class T3_FunctionalInterface {
/*
* thread_create
* 1. Runnable无返回值
* 2. Callable有返回值
*/
@Test
public void T1_runnable() {
// 1. 匿名内部类方式
new Thread(new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程已启动");
}
}).start();
// 2. Lambda表达式
new Thread(() -> {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程已启动");
}).start();
// 3. 简化Lambda
new Thread(() ->
System.out.println(Thread.currentThread().getName() + " 线程已启动")
).start();
}
/*
* T get();
*/
@Test
public void T2_supplier() {
int[] arr = {2, 3, 4, 52, 333, 23};
int maxNum = _supplier(() -> {
// 查找数组的最大值
return ArrayUtil.max(arr);
});
System.out.println(maxNum);
}
public static int _supplier(Supplier<Integer> sup) {
return sup.get();
}
/*
* void accept(T t);
*/
@Test
public void T3_consumer() {
_consumer(System.out::println);
_consumer(
s -> System.out.println(s.toLowerCase()),
s -> System.out.println(s.toUpperCase())
);
}
static void _consumer(Consumer<String> function) {
function.accept("Hello");
}
// Consumer.andThen()
static void _consumer(Consumer<String> one, Consumer<String> two) {
one.andThen(two).accept("Hello");
}
/*
* int compare(T o1, T o2);
*/
@Test
public void T4_comparator() {
String[] strs = {"xyz", "abc", "de", "fghi"};
// 匿名内部类
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
};
Arrays.sort(strs, comparator);
System.out.println(Arrays.toString(strs));
// Lambda表达式
Arrays.sort(
strs,
(s1, s2) -> s2.length() - s1.length()
);
System.out.println(Arrays.toString(strs));
}
/*
* boolean test(T t);
*
* predicate判断、断言
* & | !
*/
@Test
public void T5_predicate() {
_predicate_and(s -> s.contains("H"), s -> s.contains("W"));
_predicate_or(s -> s.contains("H"), s -> s.contains("W"));
_predicate_negate(s -> s.length() < 5);
}
/**
* 与
*/
static void _predicate_and(Predicate<String> one, Predicate<String> two) {
boolean isValid = one.and(two).test("Hello world");
System.out.println("同时包含 H、W:" + isValid);
}
/**
* 或
*/
static void _predicate_or(Predicate<String> one, Predicate<String> two) {
boolean isValid = one.or(two).test("Hello world");
System.out.println("包含 H、w 一个:" + isValid);
}
/*
* boolean test(T t);
*/
static void _predicate_negate(Predicate<String> predicate) {
boolean veryLong = predicate.negate().test("Hello world");
System.out.println("长度不小于5:" + veryLong);
}
/*
* R apply(T t);
*
* 输入、输出
*/
@Test
public void T6_function() {
String str = "10";
_function(
str,
p -> Integer.parseInt(p) + 10,
i -> i *= 10
);
str = "郑十,10";
int age = _function(
str,
s -> s.split(",")[1],
Integer::parseInt,
n -> n += 18
);
System.out.println("郑十年龄为:" + age);
}
static void _function(String str, Function<String, Integer> one, Function<Integer, Integer> two) {
int num = one.andThen(two).apply(str);
System.out.println(num + 20);
}
static int _function(String str, Function<String, String> one, Function<String, Integer> two, Function<Integer, Integer> three) {
return one.andThen(two).andThen(three).apply(str);
}
}
4. Principle
principle 英 [ˈprɪnsəpl] n. 道德原则;行为准则;规范;法则;原则;原理;观念;(行动、思想的)理由,信条;定律
/*
* lambda本质:函数式接口的匿名实现类的匿名对象(ASM技术,动态写字节码)
* lambda表达式是个语法糖
*
* JVM参数:jdk.internal.lambda.dumpProxyClasses
* 命令:java -Djdk.internal.lambda.dumpProxyClasses ClassName
* 转储得到内部类:ClassName$$Lambda$1.class
* 反编译:java -jar cfr-0.145.jar LambdaTest.class --decodelambdas false
*
* jdk7后支持java动态语言
*/
public class T4_Principle {
public static void main(String[] args) {
List<String> list = Arrays.asList("li", "song", "tao");
list.forEach(System.out::println);
}
}
/*
public class LambdaPrinciple {
public static void main(String[] args) {
List<String> strList = Arrays.asList("\u9a6c", "\u58eb", "\u5175");
strList.forEach(
(Consumer<String>)LambdaMetafactory.metafactory(
null, null, null,
(Ljava/lang/Object;)V,
lambda$main$0(java.lang.String ),
(Ljava/lang/String;)V
)());
}
private static void lambda$main$0(String s) {
System.out.println(s);
}
}
转储生成的内部类
final class LambdaPrinciple$$Lambda$1 implements Consumer {
private LambdaPrinciple$$Lambda$1() {
}
@LambdaForm.Hidden
public void accept(Object object) {
LambdaPrinciple.lambda$main$0((String)object);
}
}
*/
5. MethodRef
public class T5_MethodRef {
@FunctionalInterface
public interface Printable {
void print(String s);
}
public static void printString(Printable p) {
p.print("HelloWorld");
}
/*
* 分析:
* 为什么需要方法引用?
* Lambda所要完成的业务逻辑已经存在,已经有某个函数实现了
* 可以直接引用对应的方法(函数),即方法引用
*
* 方法引用语法:
* 对象名::方法名
*/
@Test
public void T1_methodRef() {
printString(s -> {
System.out.println(s);
});
// 简化
printString(System.out::println);
}
}
/*
public class Demo01Printable {
public static void printString(Printable p) {
p.print("HelloWorld");
}
public static void main(String[] args) {
Demo01Printable.printString((Printable)LambdaMetafactory.metafactory(
null, null, null,
(Ljava/lang/String;)V,
lambda$main$0(java.lang.String ),
(Ljava/lang/String;)V)()
);
PrintStream printStream = System.out;
Objects.requireNonNull(printStream);
Demo01Printable.printString((Printable)LambdaMetafactory.metafactory(
null, null, null,
(Ljava/lang/String;)V,
println(java.lang.String ),
(Ljava/lang/String;)V)((PrintStream)printStream)
);
}
private static void lambda$main$0(String s) {
System.out.println(s);
}
}
转储得到:java -Djdk.internal.lambda.dumpProxyClasses com.mashibing.lambda.demo05.Demo01Printable
Demo01Printable$$Lambda$1.class
Demo01Printable$$Lambda$2.class
反编译之后:java -jar cfr-0.145.jar Demo01Printable$$Lambda$1.class --decodelambdas false
final class Demo01Printable$$Lambda$1 implements Printable {
private Demo01Printable$$Lambda$1() {
}
@LambdaForm.Hidden
@Override
public void print(String string) {
Demo01Printable.lambda$main$0(string);
}
}
final class Demo01Printable$$Lambda$2 implements Printable {
private final PrintStream arg$1; // 即System.out
private Demo01Printable$$Lambda$2(PrintStream printStream) {
this.arg$1 = printStream;
}
private static Printable get$Lambda(PrintStream printStream) {
return new Demo01Printable$$Lambda$2(printStream);
}
@LambdaForm.Hidden
@Override
public void print(String string) {
this.arg$1.println(string);
}
}
*/
6. MethodRefSyntax
/*
* 类方法 / 构造方法 / 实例方法
* 条件:被引用方法与函数式接口抽象方法
* 1. 参数列表相同
* 2. 返回值类型兼容
* void兼容所有返回值类型
*/
public class T6_MethodRefSyntax {
// ---------------------------------------------- 静态方法 ----------------------------------------------
@FunctionalInterface
interface Calcable {
int calsAbs(int number);
}
public static int _static_method(int number, Calcable c) {
return c.calsAbs(number);
}
/**
* 只关注入参、返回值即可
*/
@Test
public void T1_static_Method() {
int num = _static_method(-10, n -> {
return Math.abs(n);
});
System.out.println("num = " + num);
// 简化
int num1 = _static_method(-20, Math::abs);
System.out.println("num1 = " + num1);
}
// ---------------------------------------------- 构造方法 ----------------------------------------------
@Data
@AllArgsConstructor
static class Person {
private String name;
}
@FunctionalInterface
interface PersonBuilder {
Person buildPerson(String name);
}
public static void _constructor_method(String name, PersonBuilder pb) {
Person person = pb.buildPerson(name);
System.out.println(person.getName());
}
@Test
public void T2_Constructor_Method() {
_constructor_method("迪丽热巴", name -> new Person(name));
// 简化
_constructor_method("古力娜扎", Person::new);
}
// ---------------------------------------------- 实例方法 ----------------------------------------------
@FunctionalInterface
public interface Printable {
void print(String s);
}
public static void _obj_method(Printable p) {
p.print("Hello");
}
static class ObjMethod {
public void upperCaseStr(String str) {
System.out.println(str.toUpperCase());
}
}
@Test
public void T3_Obj_Method() {
ObjMethod obj = new ObjMethod();
_obj_method(s -> {
obj.upperCaseStr(s);
});
// 简化
_obj_method(obj::upperCaseStr);
}
// ---------------------------------------------- super方法 ----------------------------------------------
@FunctionalInterface
public interface Greetable {
void greet();
}
public static void _super_method(Greetable g) {
g.greet();
}
// 父类
static class Human {
public void sayHello() {
System.out.println("Hello 我是Human!");
}
}
// 子类
static class Man extends Human {
@Override
public void sayHello() {
System.out.println("Hello 我是Man!");
}
@Test
public void T4_Super_Method() {
_super_method(() -> {
Human h = new Human();
h.sayHello();
});
// 简化
_super_method(() -> {
super.sayHello();
});
// 简化
_super_method(super::sayHello);
}
}
// ---------------------------------------------- this方法 ----------------------------------------------
@FunctionalInterface
public interface Richable {
void buy();
}
public static void _this_method(Richable r) {
r.buy();
}
static class Husband {
public void buyHouse() {
System.out.println("北京二环内买一套四合院!");
}
// 相当于一个方法
@Test
public void T5_This_Method() {
_this_method(() -> {
this.buyHouse();
});
// 简化
_this_method(this::buyHouse);
}
}
// ---------------------------------------------- array方法 ----------------------------------------------
@FunctionalInterface
public interface ArrayBuilder {
int[] buildArray(int length);
}
public static int[] _array_method(int length, ArrayBuilder ab) {
return ab.buildArray(length);
}
@Test
public void T6_Array_Method() {
int[] arr1 = _array_method(10, len -> {
return new int[len];
});
// class [I
// [:代表数组
// I:代表int
System.out.println(arr1.getClass());
System.out.println(Arrays.toString(arr1));
// 简化
int[] arr2 = _array_method(10, int[]::new);
System.out.println(Arrays.toString(arr2));
}
}