原理实现
- 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 表达式实现原理
↩
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于