JDK1.8新特性--Lambda表达式

 非原创,知识总结性文章

1、Lambda表达式的介绍

函数式编程思想概述

在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”。相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做。

传统写法代码示例

public class demo01 {
    public static void main(String[] args) {
        Runnable runnable = new Runnable(){
            public void run(){
                System.out.println("多线程任务执行");
            }
        };
        new Thread(runnable).start();
    }
}

说明:

  • Thread类需要Runnable接口作为参数,其中的抽象run方法是用来指定线程任务内容的核心;
  • 为了指定run的方法体,不得不需要Runnable接口的实现类;
  • 为了省去定义一个RunnableImpl实现类的麻烦,不得不使用匿名内部类;
  • 必须覆盖重写抽象run方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错;
  • 而实际上,似乎只有方法体才是关键所在

上述示例使用Lambda的写法

public class demo01 {
    public static void main(String[] args) {
        new Thread(()->{
            System.out.println("多线程启动");
        }).start();
    }
}

上例中,核心代码其实只是如下所示的内容:() -> System.out.println("多线程任务执行!")

Lambda标准格式

Lambda省去面向对象的条条框框,格式由3个部分组成:
  • 一些参数;
  • 一个箭头;
  • 一段代码。
    Lambda表达式的标准格式为:(参数类型 参数名称) -> { 代码语句 }
    格式说明:
  • 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔;
  • ->是新引入的语法格式,代表指向动作;
  • 大括号内的语法与传统方法体要求基本一致。

练习:使用Lambda标准格式(无参无返回)

给定一个厨子Cooker接口,内含唯一的抽象方法makeFood,且无参数、无返回值。如下:
public interface Cooker {
    void makeFood();
}

在下面的代码中,请使用Lambda的标准格式调用invokeCook方法,打印输出“吃饭啦!”字样:

public class demo01 {
    public static void main(String[] args) {
        invokeCook(() -> {
            System.out.println("吃饭啦!");
        });

    }
    private static void invokeCook(Cooker c){
        c.makeFood();
    }
}

Lambda的参数和返回值

需求:使用Lambda表达式对存在数组中的Person类型的对象数据按照年龄的降序输出。

传统写法:

public class Demo02 {
    public static void main(String[] args) {
        // 本来年龄乱序的对象数组
        Person[] array = {
            new Person("古力娜扎", 19),
            new Person("迪丽热巴", 18),
            new Person("马尔扎哈", 20) };

        // 匿名内部类
        Comparator comp = new Comparator() {
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge() - o1.getAge();
            }
        };
        Arrays.sort(array, comp); // 第二个参数为排序规则,即Comparator接口实例

        for (Person person : array) {
            System.out.println(person);
        }
    }
}

Lambda写法:

public class demo02 {
    public static void main(String[] args) {
        // 本来年龄乱序的对象数组
        Person[] array = {
                new Person("古力娜扎", 19),
                new Person("迪丽热巴", 18),
                new Person("马尔扎哈", 20) };

        Arrays.sort(array,(Person p1,Person p2) -> {
            return p2.getAge() - p1.getAge();
        });

        for (Person person : array) {
            System.out.println(person);
        }
    }
}

Lambda省略格式

  Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都可以省略。例如上例还可以使用Lambda的省略写法:
public static void main(String[] args) {
    invokeCalc(120, 130, (a, b) -> a + b);
}

省略规则:
在Lambda标准格式的基础上,使用省略写法的规则为:

  • 小括号内参数的类型可以省略;
  • 如果小括号内有且仅有一个参数,则小括号可以省略;
  • 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
    注意:关于第三点如果省略一个,那么必须同时都得省略。

2、Lambda表达式的应用

Lambda表达式的使用条件是
  • 使用lambda表达式的类型必须是一个只含有一个抽象方法的借口
  • lambda只能使用final修饰的变量

forEach遍历Map

//1.forEach遍历Map
System.out.println("\n1.forEach遍历Map");
Map map = new HashMap<>();
map.put("key1", 11);
map.put("key2", 12);
map.put("key3", 13);
map.put("key4", 14);
map.forEach((key,value)->{
    System.out.println("key:"+key+",value:"+value);
});

输出:
1.forEach遍历Map
key:key1,value:11
key:key2,value:12
key:key3,value:13
key:key4,value:14

forEach遍历List

//2.forEach遍历List
System.out.println("\n2.forEach遍历List");
List list =  new ArrayList() ;
list.add(1);
list.add(2);
list.add(3);
list.forEach(value->System.out.println(value));

输出:
2.forEach遍历List
1
2
3

在多线程中使用Lambda表达式

//3.在多线程中使用Lambda表达式
System.out.println("\n3.在多线程中使用Lambda表达式");
new Thread(()->System.out.println("new Thread start")).start();

输出:
3.在多线程中使用Lambda表达式
new Thread start

自定义Lambda表达式功能

//4.自定义Lambda表达式功能
interface MathOperator{
    int operator(int a, int b);
    
}
public static void calc(int a ,int b, MathOperator operator){
    System.out.println(operator.operator(a, b));
}

System.out.println("\n4.自定义Lambda表达式功能");
MathOperator add = (a,b)->a+b ;
MathOperator sub = (a,b)->a-b ;
MathOperator mul = (a,b)->a*b ;
MathOperator div = (a,b)->a/b ;

calc(3, 5, add);
calc(3, 5, sub);
calc(3, 5, mul);
calc(3, 5, div);

输出:
4.自定义Lambda表达式功能
8
-2
15
0

Predicate接口实现数据过滤

System.out.println("\n5.Predicate接口实现数据过滤");
List filterList = new LinkedList<>() ;
filterList.add("1");
filterList.add("abc");
filterList.add("java");
filterList.add("python2");
filterList.add("python3");
filterList.add("c++");
filture(filterList, str->str.startsWith("j")) ;
//单条件过滤
filterList.stream().filter(str->str.contains("++")).forEach(value->System.out.println(value)) ;
//多条件逻辑过滤
Predicate startWith = str->str.startsWith("p") ;
filterList.stream().filter(startWith.and(str->str.contains("2"))).forEach(value->System.out.println(value)) ;

输出:
5.Predicate接口实现数据过滤
java
c++
python2

Lambda的map和reduce操作

/3.在多线程中使用Lambda表达式
System.out.println("\n6.Lambda的map和reduce操作");
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
//map操作让每一个元素加上它之前的0.12倍
costBeforeTax.stream().map(cost -> cost+0.12*cost).forEach(System.out::println);
System.out.println(costBeforeTax.stream().reduce((sum,cost)->sum+cost).get()); //求和

输出:
6.Lambda的map和reduce操作
112.0
224.0
336.0
448.0
560.0
1500

创建一个字符串列表,每个字符串长度大于2

System.out.println("\n7.创建一个字符串列表,每个字符串长度大于2");
List strList = Arrays.asList(new String[]{"abc","de","abcde"});
List filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);

输出:
7.创建一个字符串列表,每个字符串长度大于2
Original List : [abc, de, abcde], filtered list : [abc, abcde]

获取数字的个数、最小值、最大值、总和以及平均值

System.out.println("\n8.获取数字的个数、最小值、最大值、总和以及平均值");
List 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());

输出:
8.获取数字的个数、最小值、最大值、总和以及平均值
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

你可能感兴趣的:(JDK1.8新特性--Lambda表达式)