Java8新特性---Lambda 表达式

1、Lambda 表达式

简介:是一个匿名函数,返回了是子定义接口的对象实例

  • 注意:不是所有接口都可以使用lambda 表达式,只有当接口里面只有一个需要实现的方法的时候才可以使用lambda表达式,不过并不是代表接口里面只可以写一个接口,在jdk1.8中引入了在接口的里面的方法加上default可以定义为默认的实现空方法

2、简单例子

public class ThreadDemo {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("ok");
            }
        };
        new Thread(runnable).start();
        //jdk8中
        Runnable runnable1 = () -> System.out.println("ok");
        Runnable runnable2 = () -> System.out.println("ok");
        System.out.println(runnable1 == runnable2);
        new Thread(runnable1).start();
    }
}
/*
	ok
	false
	ok
*/
//说明lambda表达式每次返回的都是一个新的对象
	    Object runnable1 = (Runnable)() -> System.out.println("ok");
        Runnable runnable2 = () -> System.out.println("ok");
        System.out.println(runnable1 == runnable2);
        new Thread((Runnable)runnable1).start();
//说明lambda表达式必须明确的指明返回类型


3、常见的四种写法

@FunctionalInterface//编译器校验,说明该接口是函数接口(单一性责任性)
interface Interface1 {
	int doubleNum(int i);
  
     
    default int add(int x , int y){ //jdk8新增加的接口默认实现方法
        return x + y;
    }
    static int sub(int x , int y){
        return x - y;
    }
}
public strictfp class LambdaDemo1 {
	public static void main(String[] args) {
      	//第一种
		Interface1 i1 = (i) -> i * 2;
		Interface1.sub(10, 3);
		System.out.println(i1.add(3, 7)); //这里调用并没有什么问题
		System.out.println(i1.doubleNum(20));
		//这种是最常见写法(当参数为1个的时候可以省略括号)
		Interface1 i2 = i -> i * 2;
		//可以指明返回值得类型
		Interface1 i3 = (int i) -> i * 2;
      	//需要多个处理的时候可以使用花括号
		Interface1 i4 = (int i) -> {
			System.out.println("-----");
			return i * 2;
		};
    }
}

4、默认函数接口

//interface IMoneyFormat{
    //String format(int i);
//}

class Money{
    private final int money;
    public Money(int money){
        this.money = money;
    }
   // public void printMoney(IMoneyFormat moneyFormat) {
        //System.out.println("我的存款:" + moneyFormat.format(this.money));
   // }
  //因为labda表达式不需要知道自己实现了什么方法名字,只Function<Integer,String>需知道输入参数是什么类		型以及返回值是什么类型即可
  //所以可以不用写接口并且可以使用jdk8自带的默认函数Function<Integer,String> Integer为输入参数类型
  //String为返回值类型
    public void printMoney(Function<Integer,String> moneyFormat) {
        System.out.println("我的存款:" + moneyFormat.apply(this.money));
    }
}
public class MyMoneyDemo {
    public static void main(String[] args) {
        Money me = new Money(99999999);
        Function<Integer, String> moneyFormat = i -> new DecimalFormat("#,###")
                .format(i);
        // 函数接口链式操作
        me.printMoney(moneyFormat.andThen(s -> "人民币 " + s));//函数表达式支持链式操作,在前面添加参数
    }
}
  • 其他相似函数
接口输入参数返回类型说明
PredicateTboolean断言
ConsumerT/消费型接口
FunctionTR输入T输出R的函数
Supplier/T提供一个数据
UnaryOperatorTT一元函数(输出输入类型相同)
BiFunction<T,U,R>T,UR2个输入的函数
BinaryOperator(T,T)T2元函数(输出输入类型相同)
public class FunctionDemo {

	public static void main(String[] args) {
		// 断言函数接口 IntPredicate自带类型的接口,有限选择使用
		IntPredicate predicate = i -> i > 0;
		System.out.println(predicate.test(-9));
	
		//
		// IntConsumer
		// 消费函数接口
		Consumer<String> consumer = s -> System.out.println(s);
		consumer.accept("输入的数据");
	}

}

5、lambda表达式的方法引用

采用的是::双冒号

class Dog {
	private String name = "哮天犬";

	/**
	 * 默认10斤狗粮
	 */
	private int food = 10;

	public Dog() {

	}

	/**
	 * 带参数的构造函数
	 * 
	 * @param name
	 */
	public Dog(String name) {
		this.name = name;
	}

	/**
	 * 狗叫,静态方法
	 * 
	 * @param dog
	 */
	public static void bark(Dog dog) {
		System.out.println(dog + "叫了");
	}

	/**
	 * 吃狗粮 JDK
	 * 
	 * 默认会把当前实例传入到非静态方法,参数名为this,位置是第一个;
	 * 
	 * @param num
	 * @return 还剩下多少斤
	 */
	public int eat(int num) {//jdk默认会把当前实例传入this默认是第一个 ,但是静态方法没有 public int eat(Dog this,int num)
		System.out.println("吃了" + num + "斤狗粮");
		this.food -= num;
		return this.food;
	}

	@Override
	public String toString() {
		return this.name;
	}
}

public class MethodRefrenceDemo {

	public static void main(String[] args) {
		Dog dog = new Dog();
		dog.eat(3);

		// 方法引用
		Consumer<String> consumer = System.out::println;
		consumer.accept("接受的数据");

		// 静态方法的方法引用
		Consumer<Dog> consumer2 = Dog::bark;//使用类名加方法名
		consumer2.accept(dog);

		// 非静态方法,使用对象实例的方法引用
		// Function<Integer, Integer> function = dog::eat;
      		//当输入和输出是一样的时候我们可以使用一元函数
		// UnaryOperator<Integer> function = dog::eat;
      		//也可以使用指定类型接口
		IntUnaryOperator function = dog::eat;
		
		// dog置空,不影响下面的函数执行,因为java 参数是传值
		dog = null;
		System.out.println("还剩下" + function.applyAsInt(2) + "斤");
		//
		// // 使用类名来方法引用
		// BiFunction<Dog, Integer, Integer> eatFunction = Dog::eat;
		// System.out.println("还剩下" + eatFunction.apply(dog, 2) + "斤");
		//
		// // 构造函数的方法引用,没有输入只有输出的函数
		// Supplier<Dog> supplier = Dog::new;
		// System.out.println("创建了新对象:" + supplier.get());
		//
		// // 带参数的构造函数的方法引用
		// Function<String, Dog> function2 = Dog::new;
		// System.out.println("创建了新对象:" + function2.apply("旺财"));

		// 测试java变量是传值还是穿引用
		List<String> list = new ArrayList<>();
		test(list);

		System.err.println(list);
	}
	private static void test(List<String> list) {
		list = null;
	}
}

6、Lambda表达式的类型推断

@FunctionalInterface
interface IMath {
	int add(int x, int y);
}
@FunctionalInterface
interface IMath2 {
	int sub(int x, int y);
}
public class TypeDemo {
	public static void main(String[] args) {
		// 变量类型定义
		IMath lambda = (x, y) -> x + y;
		// 数组里
		IMath[] lambdas = { (x, y) -> x + y };
		// 强转
		Object lambda2 = (IMath) (x, y) -> x + y;
		// 通过返回类型
		IMath createLambda = createLambda();
		TypeDemo demo = new TypeDemo();
		// 当有二义性的时候,使用强转对应的接口解决
		demo.test( (IMath2)(x, y) -> x + y);
	}
	public void test(IMath math) {
		
	}
	public void test(IMath2 math) {
		
	}
	public static IMath createLambda() {
		return  (x, y) -> x + y;
	}
}

7、Lambda表达式变量引用:

/**
 * 变量引用
 */
public class VarDemo {

	public static void main(String[] args) {
		List<String> list = new ArrayList<>();
		Consumer<String> consumer = s -> System.out.println(s + list);
		consumer.accept("1211");
	}

}

8、Lambda级联表达式和柯里化

/**
 * 级联表达式和柯里化 
 * 柯里化:把多个参数的函数转换为只有一个参数的函数 
 * 柯里化的目的:函数标准化
 * 高阶函数:就是返回函数的函数
 */
public class CurryDemo {
	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));
		Function<Integer, Function<Integer, Function<Integer, Integer>>> fun2 = x -> y -> z -> x
				+ y + z;
		System.out.println(fun2.apply(2).apply(3).apply(4));
		int[] nums = { 2, 3, 4 };
		
      Function f = fun2;
		for (int i = 0; i < nums.length; i++) {
			if (f instanceof Function) {
				Object obj = f.apply(nums[i]);
				if (obj instanceof Function) {
					f = (Function) obj;
				} else {
					System.out.println("调用结束:结果为" + obj);
				}
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值