Java8 中的Lambda表达式

对于一个新事物,我们应该从这三方面来认识,是什么?为什么会出现?怎么用?

一、Lambda表达式是什么?

它是Java8的一个新特性,正如学习一门新语言要先自己手写一个HelloWorld一样,我们先写一个Lambda表达式的HelloWorld。比如遍历输出一个List:

        List<String> list = new ArrayList<String>();
        list.add("renheng");
        list.add("fangmiao");
        //java8以前遍历集合
        for(String str : list){
            System.out.println(str);
        }
        //使用Lamada表达式遍历集合
        list.stream().forEach(str -> System.out.println(str));

1.Lambda表达式的形式化表示如下所示

Parameters -> an expression 

2.如果Lambda表达式中要执行多个语句块,需要将多个语句块以{}进行包装,如果有返回值,需要显示指定return语句,如下所示:

Parameters -> {expressions;};

3.如果Lambda表达式不需要参数,可以使用一个空括号表示,如下示例所示

() -> {for (int i = 0; i < 1000; i++) doSomething();};

二、Lambda表达式有哪些方便之处?
lambda表达式,它将允许我们将行为传到函数里。在Java 8之前,如果想将行为传入函数,仅有的选择就是匿名类,需要6行代码。而定义行为最重要的那行代码,却混在中间不够突出。Lambda表达式取代了匿名类,取消了模板,允许用函数式风格编写代码。这样有时可读性更好,表达更清晰。在Java生态系统中,函数式表达与对面向对象的全面支持是个激动人心的进步。将进一步促进并行第三方库的发展,充分利用多核CPU。我认为任何严谨的Java开发者都不应忽视此次Java发布的核心特性,即lambda表达式、函数式接口、流API、默认方法和新的Date以及Time API。作为开发人员,我发现学习和掌握lambda表达式的最佳方法就是勇于尝试,尽可能多练习lambda表达式例子。鉴于受Java 8发布的影响最大的是Java集合框架(Java Collections framework),所以最好练习流API和lambda表达式,用于对列表(Lists)和集合(Collections)数据进行提取、过滤和排序。下面是Lambda表达式的几个应用。
三、怎么使用Lambda表达式?
1.使用Lambda表达式代替匿名内部类:
那就是用() -> {}代码块替代了整个匿名类:
比如给一个按钮添加监听事件,当点击时在控制台打印一行字符串。

        Button button = new Button("点击");
        //java8以前
        button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent arg0) {
                System.out.println("点击了我一下");
            }
            
        });
        //java8
        button.addActionListener((e) -> System.out.println("点击了我一下"));

再比如想对一个Integer列表进行降序排序输出:

            List<Integer> list = Lists.newArrayList(1,2,9,5,10,11);
            //java8以前
            Collections.sort(list, new Comparator(){
                @Override
                public int compare(Object ob1, Object ob2) {
                    Integer a = (Integer)ob1;
                    Integer b = (Integer)ob2;
                    return b - a;
                }
            });
            //java8
            Collections.sort(list, (a,b) -> b-a);

Collectons的sort方法默认是按升序排列,如果要按降序排列,需要重写Comparator接口的compare方法。发现使用Lambda表达式一行代码就搞定!
2.流Stream
2.1 filter():对流过滤
任务:创建一个姓氏集合,要求出所有初始字母为L的人的总数目。使用流处理的代码如下:

            List<String> list = Lists.newArrayList("Ren","Liu","Li","Lu");
            Long count = list.stream().filter(a -> a.startsWith("L")).count();
            System.out.println("以L开头的姓氏有" + count + "个");

2.2 map():将集合类(例如列表)元素进行转换
任务:对工资表中超过3500的部分征收20%的税,得到税后的工资表。
使用流处理的代码如下:

            List<Double> salaryBeforeTax = Lists.newArrayList(4000.0,5500.0,6000.0,7000.0);
            List<Double> salaryAfterTax = salaryBeforeTax.stream().map(a -> a - (a-3500)*0.2).collect(Collectors.toList());

map方法对流中的每一个对象进行缴税操作,得到税后的工资,然后使用collect方法将这些新值转换成一个新的list。其中Collectors有toList方法,还有toSet、toMap方法等,看你想得到什么类型的集合了。
任务:将姓氏列表中的值全部转换成大写字母

         List<String> list = Lists.newArrayList("Ren","Liu","Li","Lu");
         List<String> upperList = list.stream().map(a -> a.toUpperCase()).collect(Collectors.toList());

2.3 reduce: reduce() 函数可以将所有值合并成一个,又被称为折叠操作,SQL中类似 sum()、avg() 或者 count() 的聚集函数,实际上就是 reduce 操作,因为它们接收多个值并返回一个值。
任务:对工资表超过3500的部分进行扣税(20%),并将税后的值进行相加计算总和。

List<Double> salaryBeforeTax = Lists.newArrayList(4000.0,5500.0,6000.0,7000.0);
Double sum =  salaryBeforeTax.stream().map(a -> a-(a-3500)*0.2).reduce((s,b) -> s+b).get();
System.out.println(sum);

//1.无初始值累加
T t = salaryBeforeTax.stream().reduce((a,b)->a+b);
//2.带初始值累加
Optional<T> t = salaryBeforeTax.stream().reduce("1",(a,b)->a+b);

2.4对列表的每个元素应用函数
我们通常需要对列表的每个元素使用某个函数,例如逐一乘以某个数、除以某个数或者做其它操作。这些操作都很适合用 map() 方法,可以将转换逻辑以lambda表达式的形式放在 map() 方法里,就可以对集合的各个元素进行转换了,如下所示。

// 将字符串换成大写并用逗号链接起来
List<String> G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada");
String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
System.out.println(G7Countries);
输出:USA, JAPAN, FRANCE, GERMANY, ITALY, U.K., CANADA

2.5利用流的 distinct() 方法来对集合进行去重。

// 用所有不同的数字创建一个正方形列表
List<Integer> numbers = Arrays.asList(9, 10, 3, 4, 7, 3, 4);
List<Integer> distinct = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
输出:81, 100, 9, 16, 49

2.6计算集合元素的最大值、最小值、总和以及平均值
IntStream、LongStream 和 DoubleStream 等流的类中,有个非常有用的方法叫做 summaryStatistics() 。可以返回 IntSummaryStatistics、LongSummaryStatistics 或者 DoubleSummaryStatistic s,描述流中元素的各种摘要数据。在本例中,我们用这个方法来计算列表的最大值和最小值。它也有 getSum() 和 getAverage() 方法来获得列表的所有元素的总和及平均值。

List<Double> salaryBeforeTax = Lists.newArrayList(4000.0,5500.0,6000.0,7000.0);
DoubleSummaryStatistics  summary =  salaryBeforeTax.stream().mapToDouble(a -> a).summaryStatistics();
System.out.println("最高工资:" + summary.getMax());
System.out.println("最低工资:" + summary.getMin());
System.out.println("平均工资:" + summary.getAverage());
System.out.println("工资总计:" + summary.getSum());
输出:
最高工资:7000.0
最低工资:4000.0
平均工资:5625.0
工资总计:22500.0

2.7 flatMap:把多个流合并为一个流

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

推荐阅读更多精彩内容

  • Java 8 lambda表达式示例 转自importNew 原文链接 例1、用lambda表达式实现Runnab...
    低至一折起阅读 1,361评论 0 3
  • Java8 in action 没有共享的可变数据,将方法和函数即代码传递给其他方法的能力就是我们平常所说的函数式...
    铁牛很铁阅读 1,201评论 1 2
  • 声明:本文翻译自The Java™ Tutorials(官方文档) 简述 匿名类有一个问题,如果匿名类的实现非常简...
    猴子小皮球阅读 4,619评论 0 9
  • 想做的事常被现实束缚, 想直言的话又习惯隐忍, 喜欢的人总是错过, 我们的人生啊, 仔细检查一遍又一遍, 交了答卷...
    火星之旅阅读 337评论 0 6
  • 今天朱妍起的不算早,不,应该是很迟。 她隐约记得昨天晚上起夜的时候,走廊外咯噔咯噔的高跟鞋声。她迷迷糊糊地看了看手...
    唐小茴阅读 320评论 1 0