2 Java Lambda表达式写法和应用

1、lambda语法

Java中lambda表达式的基本语法包含三个部分:
1、参数
2、-> // 一定有
3、功能体
[1] 当只有一个参数,可以不需要括号 ()。 然而,这是一个特例。
[2] 正常情况使用括号 () 包裹多个参数。 为了保持一致性,也可以使用括号 () 包裹单个参数,虽然这种情况并不常见。
[3] 如果没有参数,则必须使用括号 () 表示空参数列表。
[4] 如果功能体是单行,表达式结果自动成为Lambda表达式返回的结果
[5] 如果功能体有多行,必须使用{}包含,必须使用return表达返回结果
Lambda比匿名内部类更加易读,我们应该多多使用。

2、实际使用

List转Map

Map<String, String> collect = list.stream().collect(Collectors.toMap(i -> i, i -> i));

lambda就是一个被结构化的功能,可以被函数传递,这样能使函数的功能更加强大和语法简介。

在Java集合的使用中,充斥着大量lambda用法,使得用简单的代码就实现了复杂的功能。

Java集合的stream()返回的是Stream<T>类型的具体实现,这个实现包含存储的数据和各种操作这些数据的能力,所以你能看到sorted()、filter()、distinct()、collect()等方法。

这里我们关注collect()方法,<R, A> R collect(Collector<? super T, A, R> collector);方法声明就很厉害,

R: the type of the result

A: the intermediate accumulation type of the {@code Collector} 中间累计类型of the Collector

R: 收减操作结果类型

其实关键还是

public interface Collector<T, A, R> {} 收集操作也即reduce收减操作

 @param <T> the type of input elements to the reduction operation 输入元素的类型
 @param <A> the mutable accumulation type of the reduction operation (often
    hidden as an implementation detail) 可变中间类型
 @param <R> the result type of the reduction operation 收缩操作的结果类型

下面是工具类Collectors的toMap()方法

    public static <T, K, U>
    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                    Function<? super T, ? extends U> valueMapper) {
        return new CollectorImpl<>(HashMap::new,
                                   uniqKeysMapAccumulator(keyMapper, valueMapper),
                                   uniqKeysMapMerger(),
                                   CH_ID);
    }

其中toMap()方法的2个参数都是函数接口的子类型,也就是说可以使用lambda表达式来进行实参传递,其中T是原始输入数据的类型,K是map键的类型,U是map值的类型,Function的2个类型参数作用分别为输入类型和返回类型,所以,2个lambda表达式的作用是映射得到map的key和value,lambda表达式的输入都是输入元素,Collectors.toMap(i -> i, i -> i) 指定了从输入元素到map的key和value的映射。

3、lambda捕获的变量为什么只能用final修饰?

Java8语言上的lambda表达式只实现了capture-by-value(值捕获),也就是说它捕获的局部变量都会拷贝一份到lambda表达式的实体里,然后在lambda表达式里要变也只能变自己的那份拷贝而无法影响外部原本的变量;但是Java语言的设计者又要挂牌坊不明说自己是capture-by-value,为了以后语言能进一步扩展成支持capture-by-reference留下后路,所以现在干脆不允许向捕获的变量赋值,而且可以捕获的也只有“效果上不可变”(effectively final)的参数/局部变量。

但是Java只是不允许改变被lambda表达式捕获的变量,并没有限制这些变量所指向的对象的状态能不能变。要从lambda表达式向外传值的常见workaround之一就是用长度为1的数组:

String[] a = new String[1];
... ( () -> a[0] = "a" );
return a[0];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值