Java的lamda表达式/函数式接口/流式计算

在我们看他人code的时候经常会看到,可能会经常看到lambda表达式,函数式接口,以及流式计算。在刚接触这些新功能时,也觉得真的有必要吗?但是现在写多了,发现这个功能确实能简化代码结构,提升编码效率。lambda表达式,函数式接口,流式计算单个来用确实非常难用,但是整合到一起,就会发生非常奇妙的反应。

lambda表达式

lambda表达式允许把函数作为一个方法的参数。即,函数作为参数传递进方法。

lambda语法

(parameters) -> expression
OR
(parameters) -> {statements;}

lambada表达式的几个重要特征:

  • 可选类型声明:不需要申明参数类型,编译器可以统一识别参数类型
  • 可选参数圆括号:一个参数无需定义圆括号。但是多个参数需要定义圆括。
  • 可选大括号:如果主体只包含了一个语句,就不需要使用大括号。
  • 可选返回关键字:如果主体只有一个表达式返回值,编译器会自动返回值。
// 1. 不需要参数,直接返回值
() -> 3

// 2. 接收一个参数,返回其两倍
x -> 2 * x

// 3. 接收两个数字, 返回差
(x, y) -> x - y

lambda reference方法

public class Test {
    public int addOne(int a){
        return a;
    }
    public static int ssaddOne(int a){
        return a;
    }
    public static void main(String[] args) {
        BiFunction<Test, Integer, Integer> addOne = Test::addOne;
        Function<Integer, Integer> addOne1 = new Test()::addOne;
        Function<Integer, Integer> ssaddOne = Test::ssaddOne;
    }
}

函数式接口

什么是函数式接口

函数式接口就是有且仅有一个抽象方法的接口。(但是可以有多个非抽象方法)。
函数式接口可以被转换为lambda表达式。

四大函数式接口

java.util.function.Consumer

// 消费者:接收一个参数,没有返回值
@FunctionalInterface
public interface Consumer<T> {
    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}
-----------------------------------------------------------------------------
java.util.function.Predicate

// 断言者:接收一个参数,返回一个boolean
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}
----------------------------------------------------------------------------------
java.util.function.Supplier

// 提供者:不接受任何参数,返回会一个参数
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
--------------------------------------------------------------------------------
java.util.function.Function
// 操作者:接收一个参数,返回一个参数
@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}

下面我们来看看,lambda和函数式接口的使用。

package com.hardy;

import org.junit.Test;

import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * @description:
 * @author: Administrator
 * @time: 2022/8/21
 */
public class FunctionTest {

    @Test
    public void testConsumer(){
        Consumer<Object> consumer = new Consumer<>() {

            @Override
            public void accept(Object o) {
                System.out.println(o);
            }
        };
        consumer.accept("test");
        System.out.println("--------------------");
        // lambda
        Consumer<String> lc = (s) -> {
            System.out.println(s);
        };
        lc.accept("lambda");
        System.out.println("--------------------");
        // lambda
        Consumer<String> lc2 = (s) -> {
            System.out.println(s);
        };
        lc2.accept("lambda2");
        System.out.println("--------------------");
        // lambda
        Consumer<String> ll = System.out::println;
        ll.accept("ll");
    }

    @Test
    public void testPredicate(){
        Predicate<Integer> predicate = new Predicate<>() {
            @Override
            public boolean test(Integer o) {
                if (o > 60) {
                    return true;
                } else {
                    return false;
                }
            }
        };
        System.out.println(predicate.test(61));
        System.out.println("--------------------------");
        Predicate<Integer> predicate1 = i -> {
            return i > 60;
        };
        System.out.println(predicate1.test(50));
    }
}

如果只看lambda表达式,函数式接口,你也许会感觉就那么回事,感觉也没啥好的。但是,当你看到流式计算,你才会体会到lambda表达式和函数式接口给编程带来的简洁。

流式计算

思考:如何使用一行代码实现,下列要求:

  1. 对象的年龄大于18
  2. 性别为男性
  3. id为偶数
  4. id 倒序排列
  5. name字母大写
public class StreamTest {

    /**
     * 1. 对象的年龄大于18
     * 2. 性别为男性
     * 3. id为偶数
     * 4. id 倒序排列
     * 5. name字母大写
     */
    @Test
    public void testStream() {
//      这里模拟从数据库获取数据
        User u1 = new User(1, "name1", "male", 16);
        User u2 = new User(2, "name2", "female", 17);
        User u3 = new User(3, "name3", "male", 18);
        User u4 = new User(4, "name4", "male", 19);
        User u5 = new User(5, "name5", "male", 26);
        User u6 = new User(6, "name6", "male", 35);
        User u7 = new User(7, "name7", "male", 19);
        User u8 = new User(8, "name8", "female", 12);

        // 集合
        List<User> list = Arrays.asList(u1, u2, u3, u4, u5, u6, u7, u8);

        // stream
        List<User> users = list.stream().filter(user -> user.getAge() > 18)
                .filter(user -> user.getSex().equals("male"))
                .filter(user -> user.getId() % 2 == 0)
                .sorted(Comparator.comparingInt(User::getId))
                .peek(user -> user.setName(user.getName().toUpperCase())).collect(Collectors.toList());
        System.out.println(users);
    }
}

记住:存储交给集合,计算交给流

posted @ 2022-08-21 22:41  永和九年  阅读(104)  评论(0)    收藏  举报