【java8】java新特性——lambda表达式

时间:2022-03-21 19:40:14

一,前言

      在上一篇博客中,小编向大家抛转引玉,简单说明了[ Java8 ](http://blog.csdn.net/kisscatforever/article/details/79572194 ),其实Java 8在2014年3月18日,就发布了。可以说程序员都很激动,而我就不知道,慢慢的接触了,就发现这个东西还真是不错。

二,为什么使用Lambda表达式?

      第一次接触Lambda表达式的时候,是在学习中.net的lambda表达式,用于写入sql语句。当时自己也是通过看视频接触的,还记得当时自己也是学Linq语句,例如:

1.选择语句:books.Select(p => new {p.Title,p.UnitPrice,p.Author}); //需用匿名方式
2. where语句:books.Where(p => p.UnitPrice == 100 && p.Title =” ABC”); 

      现在在java8中,汇集了众家的所长,把lambda表达式融合过来了。可以说真是棒。什么是Lambda表达式呢?Lambda表达式就是一个匿名函数(匿名函数就是没有实际名字的函数),我们可以把LAMBDA表达式理解为一段可以传递的代码。可以写出更简洁,更灵活的代码。作为一种更紧凑的代码风格,使得java的的语言表达能力得到了提升。那拉姆达表达式的格式是什么样的呀?

      lambda表达式的基础语法:Java8引入一个新的操作符 - > 该操作符叫做箭头操作符,箭头把操作符分成两部分。左侧:lambda表达式的参数列表; 右侧:lambda表达式式中所需执行的功能,即lambda体

三,10个演示足够你使用Lambda表达式

3.1无参数,无返回值6行变1行

    @Test
    public void test1(){

        //第一种 经典型
       new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("I Love Java!!");
            }
        }).start();
        System.out.println("----------------------------------------------");
       //第二种 lambda型
        new Thread(()->System.out.println("I Love Java!!")).start();

    }

      结果:

【java8】java新特性——lambda表达式

3.2一个参数,无返回值

 @Test
    public void test2(){
        happy(1000,(x)->System.out.println("你们爱的java喜欢消费,喜欢大保健,平均:"+x+"元"));
    }

    /** * 调用消费型接口 * @param money * @param con */
    public void happy(double money, Consumer<Double> con){
        con.accept(money);
    }

      结果:
【java8】java新特性——lambda表达式

      说明:如果只有一个参数,小括号可以省略不写’happy(1000,x - > System.out.println(“你们爱的java喜欢消费,喜欢大保健,平均:”+ x +“元“)); `如果lambda中只有一条语句,返回和大括号可以省略不写.

3.3 有两个以上的参数,有返回值,并且有多条语句

      多条语句用{}括起来。如果lambda体只有一条一条语句 ,return和大括号都可以省略。

 @Test
    public void testCount(){
        Long t1= 5L;
        Long t2=9L;
        long count = count(t1, t2, (l1, l2) -> l1 + l2); System.out.println(count); System.out.println("---------------------------------------"); long count1 = count(t1, t2, (l1, l2) -> l1 * l2); System.out.println(count1); }

      结果:
【java8】java新特性——lambda表达式

四、实例

4.1 lambda表达式实现Runnable接口

      java8之前runnable接口实现方法用4行代码,使用lambda表达式只需要一行代码:

// Java 8之前:
new Thread(new Runnable() {
    @Override
    public void run() {
    System.out.println("Before Java8, too much code for too little to do");
    }
}).start();

//Java 8方式:
new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();

4.2 使用lambda表达式代替增强for循环

      做java的,肯定接触过集合类,接触过list。最常见的就是迭代、遍历其中的所有元素。java8之前的所有循环代码是顺序的,可以对其元素进行并行处理。如果想做并行过滤就要自己写代码。通过引入lambda表达式和默认方法,将做什么和怎么做的问题分开了,这意味着Java集合现在知道怎样做迭代,并可以在API层面对集合元素进行并行处理。

// Java 8之前:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String feature : features) {
    System.out.println(feature);
}

// Java 8之后:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(n -> System.out.println(n));

// 使用Java 8的方法引用更方便,方法引用由::双冒号操作符标示,
// 看起来像C++的作用域解析运算符
features.forEach(System.out::println);

4.3 lambda表达式使用Map 和Reduce

      Map 映射,接收Lambda,将元素转换成新的集合。接收一个函数作为参数,该函数会被应用到每一个元素上,并将其映射为一个新的元素。

      Reduce可以将流中元素反复结合起来,得到一个值。

  List<Employee> emps = Arrays.asList(
            new Employee(101,"张三",18,9999.99),
            new Employee(102,"李四",18,4444.66),
            new Employee(103,"王五",14,3000.99),
            new Employee(104,"赵六",55,20000.99),
            new Employee(105,"田七",66,55555.55),
            new Employee(106,"周八",77,99.99)
    );

    @Test
    public void test3(){

        //map 取出emps list 中所有名字,并打印出来
        emps.stream().map(Employee::getName).forEach(System.out::println);
        //map 把emps集合中所有人的名字取出来,放到新的list中
        List<String> collect = emps.stream().map(Employee::getName).collect(Collectors.toList());

        System.out.println("------------------------------------");

        //reduce 求和
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 55, 56, 7, 78, 8, 9);
        Integer sum = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println(sum);

        System.out.println("------------------------------------");

        //map reduce 计算所有工人的薪资总和
        Optional<Double> optional = emps.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(optional.get());

    }

      Map和Reduce操作是函数式编程的核心操作,因为其功能,reduce 又被称为折叠操作。另外,reduce 并不是一个新的操作,你有可能已经在使用它。SQL中类似 sum()、avg() 或者 count() 的聚集函数,实际上就是 reduce 操作,因为它们接收多个值并返回一个值。流API定义的 reduceh() 函数可以接受lambda表达式,并对所有值进行合并。IntStream这样的类有类似 average()、count()、sum() 的内建方法来做 reduce 操作,也有mapToLong()、mapToDouble() 方法来做转换。这并不会限制你,你可以用内建方法,也可以自己定义。在这个Java 8的Map Reduce示例里,我们首先对所有价格应用 12% 的VAT,然后用 reduce() 方法计算总和。

// 为每个订单加上12%的税
// 老方法:
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
double total = 0;
for (Integer cost : costBeforeTax) {
    double price = cost + .12*cost;
    total = total + price;
}
System.out.println("Total : " + total);

// 新方法:
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
double bill = costBeforeTax.stream().map((cost) -> cost + .12*cost).reduce((sum, cost) -> sum + cost).get(); System.out.println("Total : " + bill);

4.4 过滤一个String列表

       流提供filter方法,过滤。

      过滤是Java开发者在大规模集合上的一个常用操作,而现在使用lambda表达式和流API过滤大规模数据集合是惊人的简单。流提供了一个 filter() 方法,接受一个 Predicate 对象,即可以传入一个lambda表达式作为过滤逻辑。下面的例子是用lambda表达式过滤Java集合,将帮助理解。

// 创建一个字符串列表,每个字符串长度大于2
List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);

4.5 去重 distinct

      流的 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());
System.out.printf("Original List : %s, Square Without duplicates : %s %n", numbers, distinct);

      输出:

Original List : [9, 10, 3, 4, 7, 3, 4],  Square Without duplicates : [81, 100, 9, 16, 49]

4.6 计算集合的最大值、最小值、总和以及平均值

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

         //获取数字的个数、最小值、最大值、总和以及平均值
        List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
        IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("Highest prime number in List : " + stats.getMax()); System.out.println("Lowest prime number in List : " + stats.getMin()); System.out.println("Sum of all prime numbers : " + stats.getSum()); System.out.println("Average of all prime numbers : " + stats.getAverage());

      输出:

Highest prime number in List : 29
Lowest prime number in List : 2
Sum of all prime numbers : 129
Average of all prime numbers : 12.9

五、小结

      java 越来越好!

      近些年来,java更新的越来越好。通过新特性的学习,以后就可以更加高效率的写代码了。