Java8-Lambda表达式基础语法和内置四大核心函数式接口

Lambda表达式

Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递),其可以代替实现接口中的抽象方法时的书写匿名内部类的繁琐代码。

举个栗子:

Java中有个Runnable接口,直接使用该接口,需要重写实现其接口内部中的抽象方法。如下:

Runnable run = new Runnable() {
    @Override
    public void run() {
        System.out.println("old run");
    }
};
run.run();

该代码可以使用lambda表达式简化为:

 Runnable run1 = () -> System.out.println("lambda run");
 run1.run();

1. 基础语法

java8中引入了一个新的操作符 ->,该操作符称为箭头操作符Lambda操作符,该箭头符号将整个Lambda表达式拆分成两部分:

左侧:Lambda表达式的参数列表,即接口中对应抽象方法的参数列表

右侧:Lambda表达式中所需要执行的功能,即Lambda表达式体。即需要实现的抽象方法功能体

1.1. 语法格式一 无参数,无返回值

对应格式为: () -> 方法体... 括号内无参数

例如:() -> Sysout...

@Test
public void test1 (){
    //无参数 , 无返回值 对应格式为: () -> 方法体...   括号内无参数
    Runnable run = new Runnable() {
        @Override
        public void run() {
            System.out.println("old run");
        }
    };
    run.run();
    System.out.println("-----------");
    Runnable run1 = () -> System.out.println("lambda run");
    run1.run();
}
/*result:
    old run
    -----------
    lambda run
*/

1.2. 语法格式二 有一个参数,无返回值

对应语法格式为 (x) -> 无返回值的方法体

例如: (x) -> System.out.println(x)

有且只有一个参数左侧的小括号可以省略不写

例如: x -> System.out.println(x)

// 有一个参数 , 无返回值
@Test
public void test2(){
    List list = new ArrayList<>();
    Consumer consumer = (s) -> list.add(s);//将consumer接收到的对象进行具体的功能的消费
    consumer.accept("ddd");
    consumer.accept("aaa");
    consumer.accept("ccc");
    list.forEach(System.out::println);
    /*
        Result:
            ddd
            aaa
            ccc
     */
}

1.3. 语法格式三 有两个或两个以上参数,有返回值

两个或两个以上参数,有返回值,并且 lambda 体中有多条语句

语法为: 
(x,y) -> {
    方法体
    return 返回值
}

多条语句必须使用大括号包括在内,
有返回值,需要使用return 返回返回值.
 Comparator com = (x, y) -> {
    System.out.println("x为"+x);
    System.out.println("y为"+y);
    return Integer.compare(x,y);
    };


如果lambda体中只有一条语句,
那么大括号{}可以省略,
return关键字也可以省略

例如: 
Comparator com = (x,y) -> {
    return Integer.compare(x,y);
}

就可以简写成:

Comparator com = (x,y) -> Integer.compare(x,y);

 Lambda表达式的参数列表的 数据类型可以省略不写,
因为JVM编译器可以通过上下文推断出数据类型,即'类型推断'.

即: 
(Integer x,Integer y) -> Integer.compare(x,y);

简化成:
(x,y) -> Integer.compare(x,y);


@Test
public void test3(){
    Comparator com = (x, y) -> {
        System.out.println("x为"+x);
        System.out.println("y为"+y);
        return Integer.compare(x,y);
    };
    System.out.println(com.compare(1111,111));
    // x为1111
    // y为111
    // 1
}

利用用Java内置的Comparator接口(比较器)比较两个字符串的长度,可用lambda表达式表示为:

使用Lambda表达式直接进行该接口的核心方法体的重写

//使用Lambda表达式直接进行该接口的核心方法体的重写
Comparator com1 = (x,y) ->  {
    if(x.length() == y.length()){
        return 0;
    }else{
        if(x.length() > y.length()){
            return 1;
        }else
            return -1;

    }
};

System.out.println(com1.compare("aa","aaaaa"));// -1

2. 函数式接口

  • Lambda表达式需要函数式接口的支持

  • 函数式接口定义: 接口中只有一个抽象方法的接口,称为函数式接口。

  • 可以使用注解 @FuncitonalInterface 修饰,其修饰作用为:限定该接口必须为函数式接口,即该接口中有且只有一个抽象方法。否则无法通过编译。即可以检查是否为函数式接口

2.1. 自定义一个函数式接口:

@FunctionalInterface
public interface Operation {
    public R operation(T t1, T t2);
}

2.1.1 方案一:写具体实现方法再直接使用
public void op (Long l1, Long l2, Operation operation){
        System.out.println(operation.operation(l1,l2));
    }
@Test
public void testMyOperation(){
    op(10l,10l,(x,y) -> x*y);//100
    op(100l,200l,(x,y)-> x+y);//300
}

2.1.2 方案二: 先使用lambda表示具体实现方法体,再进行接口中的方法调用,传入具体值:
@Test
public void testMyOperation(){
    Operation  op = (x,y) -> x*y;
    System.out.println(op.operation(10,10));  //100
}

实际使用时,大多数情况下直接使用Java8内置四大函数式接口,并不要进行自己写函数式接口。


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

Consumer  消费型接口 消费对象
    void accept(T t);
Supplier  供给型接口 生成对象
    T get();
Function  函数型接口 指定特定功能
    R apply(T t);
Predicate  断言型接口 进行条件判断
    boolean test(T t); 

3.1. 消费型接口

Consumer 消费型接口
void accept(T t);

// Consumer 消费型接口
    @Test
    public void testConsumer(){
        //此时的(d) 小括号里有参数 
        //原因是因为 Consumer接口有参数 
        //void accept(T t);
        
        consume(1000,(d)-> System.out.println(d));
    }
    public void consume(Integer n , Consumer con){
        //函数接口接收 消费 形参n
        con.accept(n);
    }

3.2. 供给型接口

Supplier 供给型接口

T get();小括号无参数

 // Supplier  供给型接口
    @Test
    public void testSupplier(){
        //T get(); 小括号无参数
       List numList = getNumList(10,() -> (int)(Math.random()*101));
        for ( Integer i: numList
             ) {
            System.out.println(i);
        }

    }
    //调用此方法时,第二个参数提供一个数字集合
    public List getNumList(int n, Supplier sup){
        List numList = new ArrayList<>();

        for (int i = 0; i < n; i++){
            numList.add(sup.get()); //通过get方法得到数字 存到numList
        }
        return numList;
    }

3.3. 函数型接口

Function 函数型接口 指定特定功能

   //Function  函数型接口 特定功能
    @Test
    public void testFunction(){
        //将字符串转成大写
        String str1 = strHandler("ghslkajh", (s) -> s.toUpperCase());
        System.out.println(str1);
    }

    // Function 函数型接口
    //定义一个处理字符串功能型接口函数
    public  String strHandler(String str, Function fun){
        return fun.apply(str);
    }

3.4. 断言型接口

Predicate 条件判断

boolean test(T t); 返回boolean

 //断言型接口  Predicate
    // boolean test(T t);  返回boolean
    @Test
    public void testPredicate(){
        //返回长度大于3的字符串
        List s1 = strFilter(Arrays.asList("huzhiqi", "adaad", "1231", "414441", "gagsgasg"), (s) -> s.length() > 3);
        System.out.println(s1); //[huzhiqi, adaad, 1231, 414441, gagsgasg]
        //返回包含d的字符串
        List s2 = strFilter(Arrays.asList("huzhiqi", "adaad", "1231", "414441", "gagsgasg"), (s) -> s.contains("d"));
        System.out.println(s2); // [adaad]
    }
    //使用断言型接口过滤字符串
    public List strFilter(List strs, Predicate pred){
        List  list = new ArrayList<>();
        for (String s:strs
             ) {
            //利用断言型接口进行指定功能判断  即一个功能性条件判断
            if(pred.test(s)){
                //过滤功能
                list.add(s);
            }
        }
        return list;
    }

你可能感兴趣的:(Java8-Lambda表达式基础语法和内置四大核心函数式接口)