Lambda表达式入门

“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

函数接口

顾名思义何为函数接口和普通接口又有什么区别?
自JDK8以来接口可以有多个默认实现方法(普通接口)。

普通接口

普通接口上增加@FunctionalInterface即标识为函数接口,与其普通接口的区别在于函数接口只能有一个抽象方法,多个会报错

函数接口

JDK8为我们提供了很多函数接口在java.util.function包下。

函数接口包

函数接口给lambda带来了什么?
根据开头介绍Lambda是一个匿名函数,何为匿名函数?我们常见的匿名函数出现在Swing比较多,线程大家也知道举个例子。

public static void main(String[] args) {
        Thread thread = new Thread(()-> System.out.println("123123"));
        thread.start();
    }

这段代码很简单我们创建了个Thread,这里我们使用了需要Runnable接口的构造函数,为什么我们能使用Lambda表达式呢?因为Runnable接口遵循了函数接口设计规则。

Thread类
Runnable方法

这里我们可以看到Runnable函数接口只有一个方法然而方法没有形参所以我们可以通过()->逻辑代码这种形式去抒写。

Lambda

这里我们通过对集合的练习Lambda让大家有更深入的了解。

public class Transaction {
    private final Trader trader;
    private final int year;
    private final int value;
    public Transaction(Trader trader, int year, int value) {
        this.trader = trader;
        this.year = year;
        this.value = value;
    }
    public Trader getTrader() {
        return trader;
    }
    public int getYear() {
        return year;
    }
    public int getValue() {
        return value;
    }
}
class Trader{
    private final String name;
    private final String city;
    public String getName() {
        return name;
    }
    public String getCity() {
        return city;
    }
    public Trader(String name, String city) {
        this.name = name;
        this.city = city;
    }
}

创建集合数据。

Trader raoul = new Trader("Raoul", "Cambridge");
        Trader mario = new Trader("Mario","Milan");
        Trader alan = new Trader("Alan","Cambridge");
        Trader brian = new Trader("Brian","Cambridge");
        List<Transaction> transactions = Arrays.asList(
                new Transaction(brian, 2011, 300),
                new Transaction(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );

1、找出2011年发生的所有交易,并按交易额排序(从低到高)。

List<Transaction> list1 = transactions.stream().
filter(e->e.getYear()==2011).
sorted(Comparator.comparing(Transaction::getValue)).
collect(Collectors.toList());

首先通过transactions获取Stream API流,这里需要找出2011年所发生的的所有交易所以我们这里使用filter过滤结果集,下方是filter方法源码,可以看到需要的入参是一个函数接口,这里就可以采用Lambda。

Stream<T> filter(Predicate<? super T> predicate);

Predicate函数接口默认方法test 入参是一个泛型T,所以我们可以传递Transaction对象,返回参数是一个boolean类型,我们可以采用两种形式写Lambda可以隐式也可以显式,为了方便采用显示。
在filter之后的list已经被过滤了只有2011年的数据,又需要排序这里采用sorted,方法入参又是一个函数接口。

Stream<T> sorted(Comparator<? super T> comparator);源码
sorted(Comparator.comparing(Transaction::getValue))代码

入参我们采用了静态方法默认实现了里面的排序,静态方法入参是一个Function函数接口。

结果集

入参我们采用了语法糖Transaction::getValue = e->e.getValue(),综上所诉此阶段我们已经把2011排序之后的数据组装完成,这时候需要用到collect把组装的数据转换成集合再次输出到结果集这里就完成了筛选和排序,其实lambda和流水线差不多把需要做的事情一步一步做完之后再输出为成品。

2、交易员都在哪些不同的城市工作过

Set<String> list2 = transactions.stream().
map(e->e.getTrader().getCity()).
collect(Collectors.toSet());

map主要作用是获取对象中的特定属性,因为问题中的不同,所以我们采用toSet方法来去重,也可以采用distinct()在toList。

3、查找所有来自于剑桥的交易员,并按姓名排序

Set<Trader> list3 = transactions.stream().
map(e->e.getTrader()).
filter(e->e.getCity().equals("Cambridge")).
sorted(Comparator.comparing(Trader::getName)).
collect(Collectors.toSet());

因为Trader在Transaction所以我们需要用map把Trader抽取出来之后再进行城市过滤,过滤之后把名字排序在去重相同名字。

4、返回所有交易员的姓名字符串,按字母顺序排序

String list4 = transactions.stream().
map(e->e.getTrader().getName()).
distinct().
sorted().
reduce("",(a,b)->a+b);

通过map把所有交易员的姓名抽取出来,之后去重在通过排序默认从小到大,reduce方法就是把两个值结合起来生成新的值。
此方法效率不高因为每次迭代都会产生新的String,下方为优化代码。

tring traderStr = transactions.stream()
.map(transaction -> transaction.getTrader().getName())
.distinct()
.sorted()
.collect(joining());

5、有没有交易员是在米兰工作的

boolean list5 = transactions.stream().
anyMatch(e->e.getTrader().getCity().equals("Milan"))

anyMatch入参是一个Predicate函数接口和第一题中的filter入参一样,那为什么不用filter,这里出现个问题为什么不使用filter其效果也是一样的呀?
filter属于中间操作可以链接起来,将一个流转换成另一个流。这个操作不会去消耗流其目的是创建新的流所以还在"流水线"并未将其结果返回。与其相反,终端操作会消耗流,以产生一个最终结果,它们通常可以优化"流水线"来缩短计算时间。

6、打印生活在剑桥的交易员的所有交易额

transactions.stream().
filter(e->"Cambridge".equals(e.getTrader().getCity())).
map(Transaction::getValue).
forEach(System.out::println);

过滤出在剑桥的交易员,通过map提取出交易额在循环打印。

7、所有交易中,最高的交易额是多少

Optional<Integer> integer =  transactions.stream().
map(Transaction::getValue).
reduce(Integer::max);

这里返回值是用Optional包含的,JKD8加入的Optional预防空指针。

8、找到交易额最小的交易

Optional<Transaction> transaction = transactions.stream().
reduce((a,b)->a.getValue()<b.getValue()?a:b);

9、附加:交易额求和

int value = transactions.stream().
mapToInt(Transaction::getValue).sum();

以上就是一些基础的Lambda表达式,重要的不是去使用而是去理解该如何写,了解了函数接口之后再通过一系列的语法糖,也能随心所欲的写出Lambda,其次就是jdk自带的函数接口api比较多,用的时候还需百度,更多关于函数接口和Lambda的高级使用可以购买JDK8实战书籍。

博客链接:http://www.ljyanimo.com/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354