Java lambda 表达式

本贴最后更新于 192 天前,其中的信息可能已经时过境迁

原理实现

  • Java Lambda 表达式实现原理1

概念

JDK 8 的一个语法糖,可以对某些匿名内部类进行优化。让我们不需要关系操作什么对象,而是关系如何操作数据

核心

可推到、可省略

基本格式

(参数列表) -> {代码}

image

可以看见:Lambda 只关注函数的参数列表、数据的操作方式,而不关心接口的名称与方法

简化条件

  • 匿名内部类是一个接口
  • 匿名内部类当中只有一个抽象方法需要重写

省略规则

  • 参数类型可以省略
  • 方法体只有一句代码时,return 和代码的的分号可以省略
  • 方法体只有一个参数时,小括号可以省略
  • 如果用 idea,直接 Alt + Enter 即可。。。

代码实例

例一:

    public static int calculateNum(IntBinaryOperator operator) {
        int a = 10, b = 20;
        return operator.applyAsInt(a, b);
    }
    public void test01() {
        int res01 = calculateNum(new IntBinaryOperator() {
            @Override
            public int applyAsInt(int left, int right) {
                return left + right;
            }
        });

        int res02 = calculateNum((a, b) -> a + b);

        System.out.println(res01 == res02);
    }

例二:

    public static void printNum(IntPredicate predicate) {
        int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
        for (int i : arr) {
            if (predicate.test(i)) System.out.println(i);
        }
    }
    public void test02() {
        printNum(new IntPredicate() {
            @Override
            public boolean test(int value) {
                return value % 2 == 0;
            }
        });
      
        printNum((x) -> x % 2 == 0);
    }

例三:

    public static <R> R typeConver(Function<String, R> function) {
        String str = "12345";
        R res = function.apply(str);
        return res;
    }
    public void test03() {
        Integer num1 = typeConver(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.valueOf(s);
            }
        });

        Integer num2 = typeConver((s) -> Integer.valueOf(s));
        System.out.println(Objects.equals(num1, num2));
    }


函数式接口

前言

当我们构造一个函数式接口入参时,往往看到这样的构造:

    public static <T> CursorPageBaseResp<T> getCursorPageByMysql(IService<T> mapper, CursorPageBaseReq request, Consumer<LambdaQueryWrapper<T>> initWrapper, SFunction<T, ?> cursorColumn) {
        //游标字段类型
        Class<?> cursorType = LambdaUtils.getReturnType(cursorColumn);
        LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
        //额外条件
        initWrapper.accept(wrapper);
  • 其中的 Consumer 就是我们的入参

通常的调用如下:

   public CursorPageBaseResp<Contact> getUnReadPage(Message message, CursorPageBaseReq cursorPageBaseReq) {
        return CursorUtils.getCursorPageByMysql(this, cursorPageBaseReq, wrapper -> {
            wrapper.eq(Contact::getRoomId, message.getRoomId());
            wrapper.ne(Contact::getUid, message.getFromUid());//不需要查询出自己
            wrapper.lt(Contact::getReadTime, message.getCreateTime());//已读时间小于消息发送时间
        }, Contact::getReadTime);
    }
  • 通过 wrapper 的函数式构造进行入参

Consumer 涉及的就是一种叫“函数式接口”的类型

内置函数式接口

Java 8 给我们提供了一部分的接口类型:

接口 参数 返回类型 说明
Predicate <T> T boolean 输入某个值,输出 bool 值,用于对某值进行判定
Consumer <T> T void 输入某值,无输出。用于消费某值
Function <T,R> T R 输入某类型值,输出另种类型值,用于类型转化等
Supplier <T> None T 无输入,输出某值,用于生产某值
UnaryOperator <T> T T 输入某类型值,输出同类型值,用于值的同类型转化,如对值进行四则运算等
BinaryOperator <T> (T,T) T 输入两个某类型值,输出一个同类型值,用于两值合并等

Predicates 断言式接口

Predicate<T> :将 T 作为输入,返回一个布尔值作为输出,该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(与、或、非)。
Predicate 是一个布尔类型的函数接口,该函数只有一个输入参数。Predicate 接口包含了多种默认方法,用于处理复杂的逻辑动词(and, or,negate)

Predicate<String> predicate = (s) -> s.length() > 0;
 
predicate.test("foo");          
predicate.negate().test("foo");   
 
Predicate<Boolean> nonNull = Objects::nonNull;
Predicate<Boolean> isNull = Objects::isNull;
 
Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();


List<String> list = Arrays.asList("a11", "b232", "C111", "A1", "B");
list.stream().filter((s)->s.length()>2).forEach(System.out::println);

Functions 功能式接口

Function<T, R>:将 T 作为输入,返回 R 作为输出,他还包含了和其他函数组合的默认方法。
Function 接口接收一个参数,并返回单一的结果。默认方法可以将多个函数串在一起(compse, andThen)。

接口的实现:

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
 
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
 
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
 
    static <T> Function<T, T> identity() {
        return t -> t;
    }

Funtion 接口,定义了一个 apply 的抽象方法,接收一个泛型 T 对象,并且返回泛型 R 对象.

看看实例:

 Function<Integer,String> function = (i) ->{

            if(i == 1){
                return "1月";
            }else if(i == 2){
                return "2月";
            }
            return "没有";
        };

        System.out.println(function.apply(1));
Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
 
backToString.apply("123");     // "123"

Consumers

Consumer<T> :将 T 作为输入,不返回任何内容,表示在单个参数上的操作。
Consumer 代表了在一个输入参数上需要进行的操作。对输入参数进行操作,没有输出。

 Consumer<String>  consumer3 =  s -> {
            String s1 = s.toUpperCase();
            System.out.println(s1);
        };

consumer.accept("ss");
Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);
greeter.accept(new Person("Luke", "Skywalker"));

其实,主要是理解 Consumer,消费者,就可以了~ 主要是对入参做一些列的操作,在 stream 里,主要是用于 forEach;内部迭代的时候,对传入的参数,做一系列的业务操作,没有返回值;

Suppliers

Supplier 接口产生一个给定类型的结果。与 Function 不同的是,Supplier 没有输入参数。

Supplier<Food> supplier = Food::new;

Food food = supplier.get();

food.setRet(1);
int ret = food.getRet();
Supplier<Person> personSupplier = Person::new;
personSupplier.get();   

Comparators

Comparator 接口在早期的 Java 版本中非常著名。Java 8 为这个接口添加了不同的默认方法。

Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName)
 
Person p1 = new Person("John", "Doe")
Person p2 = new Person("Alice", "Wonderland")
 
comparator.compare(p1, p2)
comparator.reversed().compare(p1, p2)

  1. Java Lambda 表达式实现原理

    参考文章:www.google.com/search?q=...

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8207 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...