New Features of Java 8---Lambda Expression

1. Lambda expression

Introduction: It is an anonymous function that returns an object instance that is a sub-defined interface

  • Note: Not all interfaces can use lambda expressions. Lambda expressions can only be used when there is only one method that needs to be implemented in the interface, but it does not mean that only one interface can be written in the interface. It was introduced in jdk1.8 The method inside the interface plus default can be defined as the default implementation empty method

2. Simple example

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. Four common writing methods

@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. Default function interface

//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));//函数表达式支持链式操作,在前面添加参数
    }
}
  • Other similar functions
interface Input parameters Return type Description
Predicate T boolean Affirmation
Consumer T / Consumer interface
Function T R Function of input T and output R
Supplier / T Provide a data
UnaryOperator T T Unary function (the same type of output and input)
BiFunction<T,U,R> T,U R 2 input functions
BinaryOperator (T,T) T 2-variate function (the same type of output and input)
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. Method references for lambda expressions

Used:: double colon

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. Type inference of Lambda expressions

@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 expression variable reference:

/**
 * 变量引用
 */
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 cascading expressions and currying

/**
 * 级联表达式和柯里化 
 * 柯里化:把多个参数的函数转换为只有一个参数的函数 
 * 柯里化的目的:函数标准化
 * 高阶函数:就是返回函数的函数
 */
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);
				}
			}
		}
	}
}

Guess you like

Origin blog.csdn.net/JISOOLUO/article/details/104350974