原理实现
- Java Lambda 表达式实现原理1
概念
JDK 8 的一个语法糖,可以对某些匿名内部类进行优化。让我们不需要关系操作什么对象,而是关系如何操作数据
核心
可推到、可省略
基本格式
(参数列表) -> {代码}
可以看见: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)
Java Lambda 表达式实现原理
↩
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于