Nuevas funciones de Java 8 --- Expresión Lambda

1. Expresión lambda

Introducción: es una función anónima que devuelve una instancia de objeto que es una interfaz subdefinida

  • Nota: No todas las interfaces pueden usar expresiones lambda. Las expresiones lambda solo se pueden usar cuando solo hay un método que debe implementarse en la interfaz, pero eso no significa que solo se pueda escribir una interfaz en la interfaz. Se introdujo en jdk1.8 El método dentro de la interfaz más el valor predeterminado se puede definir como el método vacío de implementación predeterminado

2. Ejemplo sencillo

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. Cuatro métodos de escritura habituales

@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. Interfaz de función predeterminada

//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));//函数表达式支持链式操作,在前面添加参数
    }
}
  • Otras funciones similares
interfaz Parámetros de entrada Tipo de retorno Descripción
Predicado T booleano Afirmación
Consumidor T / Interfaz del consumidor
Función T R Función de la entrada T y la salida R
Proveedor / T Proporcionar un dato
UnaryOperator T T Función unaria (el mismo tipo de salida y entrada)
BiFunción <T, U, R> T, U R 2 funciones de entrada
BinaryOperator (T, T) T Función de 2 variables (el mismo tipo de salida y entrada)
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. Referencias de métodos para expresiones lambda

Usado :: dos puntos dobles

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. Inferencia de tipos de expresiones 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. Referencia de variable de expresión 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. Expresiones en cascada lambda y curry

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

Supongo que te gusta

Origin blog.csdn.net/JISOOLUO/article/details/104350974
Recomendado
Clasificación