JAVASEday18 Lembda表达式

Lembda表达式

Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

基本语法

Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “ ->” , 该操作符被称为 Lambda 操作符或箭头操作符。它将 Lambda 分为两个部分:
左侧: 指定了 Lambda 表达式需要的所有参数
右侧: 指定了 Lambda 体,即 Lambda 表达式要执行的功能。

/*
 * 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符
 * 						    箭头操作符将 Lambda 表达式拆分成两部分:
 * 
 * 左侧:Lambda 表达式的参数列表
 * 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
 * 
 * 语法格式一:无参数,无返回值
 * 		() -> System.out.println("Hello Lambda!");
 * 
 * 语法格式二:有一个参数,并且无返回值
 * 		(x) -> System.out.println(x)
 * 
 * 语法格式三:若只有一个参数,小括号可以省略不写
 * 		x -> System.out.println(x)
 * 
 * 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
 *		Comparator<Integer> com = (x, y) -> {
 *			System.out.println("函数式接口");
 *			return Integer.compare(x, y);
 *		};
 *
 * 语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
 * 		Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
 * 
 * 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
 * 		(Integer x, Integer y) -> Integer.compare(x, y);
 * 
 * 上联:左右遇一括号省
 * 下联:左侧推断类型省
 * 横批:能省则省
 * 
 * 二、Lambda 表达式需要“函数式接口”的支持
 * 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。 可以使用注解 @FunctionalInterface 修饰
 * 			 可以检查是否是函数式接口
 */
public class TestLambda2 {
	
	@Test
	public void test1(){
		int num = 0;//jdk 1.7 前,必须是 final,而jdk1.8会自动将内部类中的变量声明为final类型。
 
		Runnable r = new Runnable() {
			@Override
			public void run() {
				System.out.println("Hello World!" + num);//此处如果改为num++依旧是不可行的,因为jdk1.8只是将其隐式声明final类型而已。
			}
		};
		
		r.run();
		
		System.out.println("-------------------------------");
		
		Runnable r1 = () -> System.out.println("Hello Lambda!");
		r1.run();
	}
	
	@Test
	public void test2(){
		Consumer<String> con = x -> System.out.println(x);
		con.accept("我大尚硅谷威武!");
	}
	
	@Test
	public void test3(){
		Comparator<Integer> com = (x, y) -> {
			System.out.println("函数式接口");
			return Integer.compare(x, y);
		};
	}
	
	@Test
	public void test4(){
		Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
	}
	
	
//对于语法格式6中JVM类型推断的的内容,我们可以这样理解。
 
	@Test
	public void test5(){
		String[] strs = {"aaa", "bbb", "ccc"};//这样是可行的,因为JVM会做类型推断。
//      String[] strs;
//      strs = {"aaa", "bbb", "ccc"}; 这样是不可行的,因为JVM虚拟机做不了类型推断
		List<String> list = new ArrayList<>();
		
		show(new HashMap<>());
	}
 
	public void show(Map<String, Integer> map){
		
	}

上述 Lambda 表达式中的参数类型都是由编译器推断得出的。 Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。 Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”.

函数式接口

只包含一个抽象方法的接口,称为函数式接口。但我们通常并不自己去写一个函数式接口供自己使用,java已经提供了内置的四大核心函数式接口。
在这里插入图片描述

/*
 * Java8 内置的四大核心函数式接口
 * 
 * Consumer<T> : 消费型接口
 * 		void accept(T t);
 * 
 * Supplier<T> : 供给型接口
 * 		T get(); 
 * 
 * Function<T, R> : 函数型接口
 * 		R apply(T t);
 * 
 * Predicate<T> : 断言型接口
 * 		boolean test(T t);
 * 
 */
public class TestLambda3 {
	
	//Predicate<T> 断言型接口:
	@Test
	public void test4(){
		List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok");
		List<String> strList = filterStr(list, (s) -> s.length() > 3);
		
		for (String str : strList) {
			System.out.println(str);
		}
	}
	
	//需求:将满足条件的字符串,放入集合中
	public List<String> filterStr(List<String> list, Predicate<String> pre){
		List<String> strList = new ArrayList<>();
		
		for (String str : list) {
			if(pre.test(str)){
				strList.add(str);
			}
		}
		
		return strList;
	}
	
	//Function<T, R> 函数型接口:
	@Test
	public void test3(){
		String newStr = strHandler("\t\t\t 我大尚硅谷威武   ", (str) -> str.trim());
		System.out.println(newStr);
		
		String subStr = strHandler("我大尚硅谷威武", (str) -> str.substring(2, 5));
		System.out.println(subStr);
	}
	
	//需求:用于处理字符串
	public String strHandler(String str, Function<String, String> fun){
		return fun.apply(str);
	}
	
	//Supplier<T> 供给型接口 :
	@Test
	public void test2(){
		List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100));
		
		for (Integer num : numList) {
			System.out.println(num);
		}
	}
	
	//需求:产生指定个数的整数,并放入集合中
	public List<Integer> getNumList(int num, Supplier<Integer> sup){
		List<Integer> list = new ArrayList<>();
		
		for (int i = 0; i < num; i++) {
			Integer n = sup.get();
			list.add(n);
		}
		
		return list;
	}
	
	//Consumer<T> 消费型接口 :
	@Test
	public void test1(){
		happy(10000, (m) -> System.out.println("你们刚哥喜欢大宝剑,每次消费:" + m + "元"));
	} 
	
	public void happy(double money, Consumer<Double> con){
		con.accept(money);
	}
}

这四大接口还有他们的子接口
在这里插入图片描述

方法引用与构造器引用

方法引用

我们先来看一下什么是方法引用:方法引用其实是Lambda表达式的另一种写法,
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用.
注意:实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
方法引用:使用操作符 “ ::” 将方法名和对象或类的名字分隔开来。
如下三种主要使用情况:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法
 public static void main(String[] args) {
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("哈哈");
        Consumer<String> consumer2=x-> System.out.println(x);
        consumer2.accept("呵呵");
        //再次对Lambda表达式简写
        //这种简写叫做方法引用
        //你对接口中的抽象方法的实现逻辑中调用的这个方法,跟接口中的这个方法的返回值和形参列表一致的化,就可以用方法引用再次简写
        Consumer<String> consumer3=System.out::println;
        consumer3.accept("哈哈哈哈哈");
        System.out.println("--------------------------------");
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {//一个参数,一个返回值
                int i = Integer.parseInt(s);//一个参数,一个返回值
                return i;
            }
        };
        Function<String, Integer> function2 =(x)->Integer.parseInt(x);
        Function<String, Integer> function3=Integer::parseInt;
        System.out.println("-------------------------");
        BiFunction<Double, Double, Double> biFunction = new BiFunction<Double, Double, Double>() {
            @Override
            public Double apply(Double aDouble, Double aDouble2) {
                Math.max(aDouble, aDouble2);
                return null;
            }
        };
        BiFunction<Double, Double, Double> biFunction2=(a,b)->Math.max(a,b);
        //方法引用
        BiFunction<Double, Double, Double> biFunction3=Math::max;
        System.out.println("--------------------------");
        Function<Integer, String> function1 = new Function<Integer, String>() {
            @Override
            public String apply(Integer s) {
                String s1 = String.valueOf(s);
                return s1;
            }
        };
        Function<Integer, String> function4=String::valueOf;
    }
构造器引用

格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!

  //构造引用
        Supplier<MyClass> supplier = new Supplier<MyClass>() {
            @Override
            public MyClass get() {
                return new MyClass();
            }
        };
        Supplier<MyClass> supplier2 = () -> new MyClass();
        //构造引用
        Supplier<MyClass> supplier3 = MyClass::new;
        Function<String, MyClass> function = new Function<String, MyClass>() {
            @Override
            public MyClass apply(String s) {
                return new MyClass(s);
            }
        };
        MyClass zhangsan = function.apply("zhangsan");
        Function<String, MyClass> function2 =(s)->new MyClass(s);
        Function<String, MyClass> function3 =MyClass::new;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值