Java8之Lambda表达式

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

一、Lambda表达式语法
Lambda表达式在Java语言中引入了一个新的语法元素和操作符。这个操作符为“->”,该操作符被称为Lambda操作符或剪刀操作符。
它将Lambda分为两个部分:
左侧: 指定了Lambda表达式需要的所有参数
右侧: 指定了Lambda体,即Lambda表达式要执行的功能。
   语法格式一: 无参,无返回值,Lambda体只需要一条语句
        /*
        语法格式一:无参,无返回值,Lambda体只需要一条语句
         */
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello");
            }
        };
        Runnable runnable1 = () -> System.out.println("Hello Lambda");
        runnable.run();
        runnable1.run();
   语法格式二:Lambda 需要一个参数
Consumer<String> fun = (e) -> System.out.println(e);
fun.accept("Hello lambda");
    语法格式三: Lambda只需要一个参数时,参数的小括号可以省略
Consumer<String> fun = e -> System.out.println(e);
fun.accept("Hello lambda");
   语法格式四:Lambda需要两个参数,并且有返回值
Comparator<Integer> comparator = (x,y) -> {
            System.out.println("函数式接口");
            return Integer.compare(x,y);
        };
        int result = comparator.compare(10,2);
        System.out.println(result);
        /*
            非lambda表达式
         */
        Comparator<Integer> comparator1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer x, Integer y) {
                System.out.println("函数式接口");
                return Integer.compare(x,y);
            }
        };
    语法格式五:当Lambda体只有一条语句时,return与大括号可以省略
Comparator<Integer> comparator = (x,y) ->  Integer.compare(x,y);;
        int result = comparator.compare(10,2);
        System.out.println(result);
    语法格式六: 数据类型可以省略,因为可由编译器推断得出,称为“类型推断”.通常省略数据类型!
Comparator<Integer> comparator = (Integer x,Integer y) ->  Integer.compare(x,y);
    注:类型推断
上述Lambda 表达式中的参数类型都是由编译器推断得出的。Lambda 表达式中无需指定类型,程序依然可以编译,这是因为javac根据程序的上下文,在后台推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”。



二、函数式接口
什么是函数式接口?
只包含一个抽象方法的接口,称为函数式接口。
你可以通过Lambda 表达式来创建该接口的对象。(若Lambda 表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)。
我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时javadoc也会包含一条声明,说明这个接口是一个函数式接口。

自定义函数式接口
不使用泛型
@FunctionalInterface
public interface MyNumber {
    public double getValue();

}
使用泛型的函数式接口
@FunctionalInterface
public interface MyNumber<T> {
    public double getValue(T t);
}

作为参数传递Lambda表达式
作为参数传递Lambda表达式:为了将Lambda表达式作为参数传递,接收Lambda表达式的参数类型必须是与该Lambda表达式兼容的函数式接口的类型。

Java内置四大核心函数式接口

函数式接口
参数类型
返回类型
用途
Consumer<T>
消费型接口
T
void
对类型为T的对象应用操作。
包含方法:void accept(T t)
Supploer<T>
供给型接口
T
返回类型为T的对象。
包含方法:T get();
Function<T,R>
函数型接口
T
R
对类型为T的对象应用操作,并返回结果。结果是R类型的对象。
包含方法:R apply(T t);
Predicate<T>
断定型接口
T

boolean
确定类型为T的对象是否满足某约束,并返回boolean值。
包含的方法: boolean test(T t);
//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);
    }


其他接口

函数式接口
参数类型
返回类型
用途
BigFunction<T,U,R>
T,U
R
对类型为T,U参数应用操作,返回R类型的结果。
包含方法:R apply(T t,U u);
UnaryOperator<T>
(Function子接口)
T
T
对类型为T的对象进行一元运算,并返回T类型的结果。
包含方法:T apply(T t);
BinaryOperator<T>
(BigFunction子接口)
T,T
T
对类型为T的对象进行二元运算,并返回T类型的结果。
包含方法:T apply(T t1,T t2);
BigConsumer<T,U>
T,U
void
对类型为T,U参数应用操作。
包含方法:void accept(T t,U u)
ToIntFunction<T>
ToLongFunction<T>
ToDoubleFunction<T>
T
int
long
double
分别计算int,long,double值的函数
IntFunction<R>
LongFunctiin<R>
DoubleFunction<R>
int
long
double
R
参数分别为int,long,double类型的函数


三、方法引用
当要传递给Lambda体的操作,已经有实现的方法了,就可以使用方法引用!(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致,以及返回值也需要一样!)
方法引用使用操作符  ::  将方法名和对象或类的名字分割开来。
方式一:对象::实例方法
//对象的引用::实例的方法名
@Test
public void   test () {
Employee   employee   =   new   Employee ( 101 , "zhouying" ) ;

Supplier < String >   supplier   =   ()   ->   employee . getName () ;
System . out . println ( supplier . get ()) ;

System . out . println ( "------------------------------------" ) ;

Supplier < String >   supplier1   =   employee::getName ;
System . out . println ( supplier1 . get ()) ;
}

@Test
public void   test1 () {
PrintStream   printStream   =   System . out ;
Consumer < String >   consumer   =   ( x )   ->   printStream . println ( x ) ;
consumer . accept ( "Hello zy!" ) ;

System . out . println ( "------------------------------------" ) ;

Consumer < String >   consumer1   =   printStream::println ;
consumer1 . accept ( "Hello Java8" ) ;

System . out . println ( "------------------------------------" ) ;

Consumer < String >   consumer2   =   System . out ::println ;
consumer2 . accept ( "Hello " ) ;

方式二:类::静态方法
//类名::静态方法名
@Test
public void   test2 () {
Comparator < Integer >   comparator   =   ( x , y )   ->   Integer . compare ( x , y ) ;
int   result   =   comparator . compare ( 1 , 2 ) ;
System . out . println ( result ) ;
System . out . println ( "-----------------------------------" ) ;
Comparator < Integer >   comparator1   =   Integer ::compare ;
int   result2   =   comparator1 . compare ( 10 , 9 ) ;
System . out . println ( result2 ) ;
}

@Test
public void   test3 () {
BiFunction < Double , Double , Double >   function   =   ( x , y )   ->   Math . max ( x , y ) ;
System . out . println ( function . apply ( 1.5 , 22.2 )) ;

System . out . println ( "----------------------------------------" ) ;

BiFunction < Double , Double , Double >   function1   =   Math ::max ;
System . out . println ( function1 . apply ( 1.2 , 1.5 )) ;
}
方式三:类::实例方法
/ /类名::实例方法名
@Test
public void   test4 () {
BiPredicate < String , String >   biPredicate   =   ( x , y )   -> x . equals ( y ) ;
System.out.println(biPredicate.test("abccde","abccde"));

System.out.println("------------------------------------------");

BiPredicate < String , String >   biPredicate1   =   String ::equals ;
System.out.println(biPredicate1.test("a","a"));

System.out.println("------------------------------------------");

Function < Employee , String >   function   =   ( e )   -> e . toString () ;
System . out . println ( function . apply ( new   Employee ())) ;

System.out.println("------------------------------------------");

Function < Employee , String >   function1   =   Employee ::toString ;
System . out . println ( function1 . apply ( new   Employee ())) ;

}


四、构造器引用
构造器的参数列表,需要与函数式接口中参数列表保持一致
方式一:类名::new
//构造器引用
@Test
public void   test6 () {
Supplier < Employee >   supplier   =   ()   ->   new   Employee () ;
System.out.println(supplier.get());

System.out.println("---------------------------------");
Supplier < Employee >   supplier1   =   Employee :: new ;
System.out.println(supplier1.get());

System.out.println("---------------------------------");
Function < String , Employee >   function   =   ( x )   ->   new   Employee ( x ) ;
Employee   employee   =   function . apply ( "zy" ) ;
System.out.println(employee);

Function < String , Employee >   function1   =   Employee :: new ;
Employee   employee1   =   function1 . apply ( "yz" ) ;
System.out.println(employee1);
}

输出如下:
Employee{id=null, name='null'}
---------------------------------
Employee{id=null, name='null'}
---------------------------------
Employee{id=null, name='zy'}
Employee{id=null, name='yz'}



五、数组引用
方式一:类型[]::new
//数组引用
@Test
public void   test10 () {
Function < Integer , Employee [] >   function   =   Employee [] :: new ;
Employee []   employees   =   function . apply ( 10 ) ;
System.out.println(employees.length);
}










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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值