public class Test {
public static void main(String [] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("ok");
}
}).start();
// 等同于
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("ok");
}
};
new Thread(runnable).start();
// 切换成Lambda表达式的写法如下
new Thread(()-> System.out.println("okk")).start();
// 等同于
Runnable runnable1 = ()-> System.out.println("okk");
new Thread(runnable1).start();
}
}
interface Interface1 {
int doubleNum(int i);
}
public class LambdaDemo1 {
public static void main(String[] args) {
// 写法1:常见写法
Interface1 i1 = (i) -> i*2; // 如果是一个参数可以去掉括号, Interface1 i1 = i -> i*2;
// 写法2:
Interface1 i2 = (int i) -> i*2;
// 写法3:
Interface1 i3 = (int i) -> {
return i*2;
};
}
}
@FunctionalInterface
,表示接口是函数接口,注解修饰的函数只存在一个需要实现的抽象方法(需要实现的方法只有一个,不是只有一个方法,还可以有默认方法)@FunctionalInterface
interface Interface1 {
int doubleNum(int i);
}
@FunctionalInterface
interface Interface1 {
int doubleNum(int i);
default int add(int x, int y) {
return x+y;
}
}
public class LambdaDemo1 {
public static void main(String[] args) {
Interface1 interfaceImpl = i -> i*3;
System.out.println(interfaceImpl.doubleNum(3)); // 输出结果为9,因为上方实现了对应的方法
System.out.println(interfaceImpl.add(3, 4)); // 输出结果为7,因为接口中有默认方法
}
}
@FunctionalInterface
interface Interface1 {
int doubleNum(int i);
default int add(int x, int y) {
return x+y;
}
}
@FunctionalInterface
interface Interface2 {
int doubleNum(int i);
default int add(int x, int y) {
return x+y+1;
}
}
@FunctionalInterface
interface Interface3 extends Interface1, Interface2 { // 编译器会提示要求重新实现add方法内容
@Override
default int add(int x, int y) {
return Interface1.super.add(x, y); // 相当于调用了Interface1的接口内容,当然我们也可以写自己的实现
}
}
public class LambdaDemo1 {
public static void main(String[] args) {
Interface3 interfaceImpl = i -> i*3;
System.out.println(interfaceImpl.doubleNum(3)); // 输出结果为9
System.out.println(interfaceImpl.add(3, 4)); // 输出结果为7
}
}
使用现成的函数接口的好处就是不用定义过多的接口,且函数接口可以支持链式操作
import java.text.DecimalFormat;
import java.util.function.Function;
interface IMoneyFormat {
String format(int i);
}
class MyMoney {
private final int money;
public MyMoney(int money) {
this.money = money;
}
// public void printMoney(IMoneyFormat iMoneyFormat) {
// System.out.println("我的存款: "+ iMoneyFormat.format(this.money));
// }
// 此时由于我们的接口只需要知道输入是什么,输出是什么,故采用Function函数接口即可
public void printMoney(Function<Integer, String> iMoneyFormat) {
System.out.println("我的存款: "+ iMoneyFormat.apply(this.money));
}
}
public class MoneyDemo {
public static void main(String[] args) {
MyMoney me = new MyMoney(9999);
// IMoneyFormat iMoneyFormat = (money)-> new DecimalFormat("#,###").format(money);
// me.printMoney(iMoneyFormat);
// 采用函数接口的方式实现如下
me.printMoney((money)-> new DecimalFormat("#,###").format(money));
// 输出: 我的存款: 9,999
// 采用函数接口链式操作特性添加前缀实现如下
Function<Integer, String > moneyFormat = (money)-> new DecimalFormat("#,###").format(money);
me.printMoney(moneyFormat.andThen( s -> "人民币 " + s));
// 输出: 我的存款: 人民币 9,999
}
}
接口 | 输入类型 | 返回类型 | 说明 |
---|---|---|---|
Predicate | T | boolean | 断言 |
Consumer | T | / | 消费一个数据 |
Function |
T | R | 输入T输出R的函数 |
Supplier | / | T | 提供一个数据 |
UnaryOperator | T | T | 一元函数(输出输入类型相同) |
BiFunction |
(T, U) | R | 2个输入的函数 |
BinaryOperator | (T, T) | T | 二元函数(输出输入类型相同) |
Predicate
也可以写成IntPredicate
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.IntPredicate;
import java.util.function.Predicate;
public class Test2 {
public static void main(String[] args) {
// 断言函数: 用于判断输入是否大于0
Predicate<Integer> predicate = i -> i > 0;
System.out.println(predicate.test(-2)); // 输出: false
// 对于基本数据类型,jdk有对应数据类型,上述内容等同如下
IntPredicate predicate1 = i -> i > 0;
// 消费函数
Consumer<String> customer = s -> System.out.println("输入的内容是: " + s);
customer.accept("巴啦啦小魔仙"); // 输出: 输入的内容是: 巴啦啦小魔仙
// 二元函数
BinaryOperator<Integer> testAdd = (a, b) -> a + b;
System.out.println(testAdd.apply(2, 3)); // 输出:5
}
}
类名::方法名
对象实例::方法名
类名::方法名
- 注意第一个参数是对象实例类名::new
import java.util.function.*;
class Dog {
private String name = "哮天犬";
public Dog() {
}
public Dog(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
public static void bark(Dog dog) {
System.out.println(dog + "叫了");
}
public static void sleep(String name) {
System.out.println(name + "默默的睡觉...");
}
private int food = 10;
/**
* 吃狗粮
*
* @param num
* @return
*/
public int eat(int num) {
System.out.println("吃了"+ num + "斤狗粮");
this.food -= num;
return this.food;
}
}
public class MethodReferenceDemo {
public static void main(String[] args) {
Consumer<String> consumer = s -> System.out.println(s);
consumer.accept("使用函数接口"); // 输出: 使用函数接口
// 如果内部方法的参数跟参数相同,则可以变成 方法引用 的方式进行书写
Consumer<String> consumer1 = System.out::println;
consumer1.accept("使用方法引用"); // 输出: 使用方法引用
// 静态方法的方法引用: 使用类名::方法名
Consumer<Dog> dogConsumer = Dog::bark;
Dog dog = new Dog();
dogConsumer.accept(dog); // 输出: Dog{name='哮天犬'}叫了
Consumer<String> simpleConsumer = Dog::sleep;
simpleConsumer.accept("旺财"); // 输出: 旺财默默的睡觉...
// 非静态方法
// 使用对象实例来引用
IntUnaryOperator function = dog::eat;
System.out.println("还剩下" + function.applyAsInt(2) + "斤"); // 输出: 吃了2斤狗粮 还剩下8斤
// 使用类名来引用,费静态方法其实默认第一个参数是当前实例this,故直接给定实例为入参即可
BiFunction<Dog, Integer ,Integer> biFunction = Dog::eat;
System.out.println("还剩下"+ biFunction.apply(dog, 3)+"斤"); // 输出: 吃了3斤狗粮 还剩下5斤
// 构造函数的方法引用, 构造函数的输入是指定参数, 输出是实例对象
// 方法名是new
// 无参构造函数如下
Supplier<Dog> supplier = Dog::new;
System.out.println("创建了一个新对象: " + supplier.get()); // 输出: 创建了一个新对象: Dog{name='哮天犬'}
// 有参构造函数如下
Function<String, Dog> dogFunction = Dog::new;
System.out.println("创建了个一个来福对象: " + dogFunction.apply("来福")); // 输出: 创建了个一个来福对象: Dog{name='来福'}
}
}
@FunctionalInterface
interface IMath1 {
int add(int x, int y);
}
@FunctionalInterface
interface IMath2 {
int add(int x, int y);
}
public class Test3 {
public static void main(String[] args) {
// 变量定义
IMath1 lambda = (x, y) -> x+y;
// 数组中
IMath1[] lambdas = {(x, y) -> x+y};
// 强转
Object lambda2 = (IMath1)(x,y) -> x+y;
// 通过方法返回类型
IMath1 createLambda = createLambda();
// 当有二义性的时候,需要使用强转指定对应的接口
Test3 test3 = new Test3();
test3.test((IMath1) (x, y) -> x+y); // 如果转换类型则会报错
}
// 当有重载方法时,无法直接匹配
public void test(IMath1 iMath1) {
}
public void test(IMath2 iMath2) {
}
static IMath1 createLambda() {
return ((x, y) -> x+y);
}
}
import java.util.function.Function;
public class Test4 {
public static void main(String[] args) {
// 实现了x+y的级联表达式
Function<Integer, Function<Integer, Integer>> fun = x -> y -> x+y;
System.out.println(fun.apply(2).apply(3)); // 输出5
Function<Integer, Function<Integer, Function<Integer, Integer>>> fun2 = x -> y -> z -> x+y+z;
System.out.println(fun2.apply(1).apply(2).apply(3));
}
}