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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值