一、Lambda表达式

1.1 什么是Lambda表达式?

Lambda表达式是JDK8中一个语法糖。他可以对某些匿名内部类的写法进行简化。它是函数式编程思想的一个重要体现。让我们不用关注是什么对象。而是更关注我们对数据进行了什么操作。
Lambda表达式主要运用在将匿名内部类代码进行优化,当接口中只有且只有一个抽象方法的时候,我们可以将这个方法使用Lambda表达式进行优化
基本语法:

  1. (参数列表)->{代码体}

1.2 省略规则

  1. 参数类型可以省略
  2. 方法体只有一句代码时大括号return和唯一一句代码的分号可以省略
  3. 方法只有一个参数时小括号可以省略(方法没有参数时必须加上小括号)
  4. 以上这些规则都记不住也可以省略不记

    1.3 练习

    1.3.1 创建线程时

    ```java // 原始写法: new Thread(new Runnable(){ @Override public void run() {
    1. System.out.println("Hello World");
    } }).start();

//Lambda表达式 new Thread(() -> System.out.println(“Hello World”)).start();

  1. <a name="glChi"></a>
  2. ### 1.3.2 IntBinaryOperator类
  3. ```java
  4. public static int calculateNum(IntBinaryOperator operator){
  5. int a = 10;
  6. int b = 20;
  7. return operator.applyAsInt(a, b);
  8. }
  9. // 原始写法
  10. public static void main(String[] args) {
  11. int i = calculateNum(new IntBinaryOperator(){
  12. @Override
  13. public int applyAsInt(int left,int right){
  14. return left + right;
  15. }
  16. });
  17. System.out.println("i = " + i);
  18. }
  19. //Lambda表达式
  20. public static void main(String[] args) {
  21. int i = calculateNum((int left, int right) -> {
  22. return left + right;
  23. });
  24. System.out.println("i = " + i);
  25. }

二、Stream流式编程

2.1 概念

Java8的Stream使用的是函数式编程模式,如同它的名字一样,它可以被用来对集合或数组进行链状流式的操作。可以更方便的让我们对集合或数组操作。
我们可以将数组或集合转换成流来进行操作,每个流都必须要有终结操作才能被执行

2.2 创建流

2.2.1 单列集合

  1. List<Author> authors = getAuthors();
  2. Stream<Author> stream = authors.stream();

2.2.2 数组

  1. Integer[] arr = {1,2,3,4,5};
  2. Stream<Integer> stream = Arrays.stream(arr);
  3. Stream<Integer> stream2 = Stream.of(arr);

2.2.3 双列集合

  1. Map<String,Integer> map = new HashMap<>();
  2. map.put("蜡笔小新",19);
  3. map.put("黑子",17);
  4. map.put("日向翔阳",16);
  5. Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();

2.3 流的中间操作

2.3.1 filter方法

可以对流中的元素进行条件过滤,符合过滤条件的才能继续留在流中。

  1. // 例如:打印集合中姓名长度大于1的作者名字
  2. List<Author> authors = getAuthors();
  3. authors.stream()
  4. .filter(author -> author.getName().length() > 1)
  5. .forEach(author -> System.out.println(author.getName()));
  6. //实际上,是去调用内部的test方法,我们通过匿名内部类的形式可以看出
  7. authors.stream()
  8. .filter(new Predicate<Author>() {
  9. @Override
  10. public boolean test(Author author) {
  11. return author.getName().length() > 1;
  12. }
  13. })
  14. .forEach(item -> System.out.println(item.getName()));

2.3.2 map方法

可以把对流中的元素进行计算或转换。实际上是调用了内部的apply()方法,通过给Function接口指定泛型,就可以将我们流中原来的元素类型,转换成指定类型。后续操作的就是该类型了。

  1. List<Author> authors = getAuthors();
  2. authors.stream()
  3. .map(new Function<Author, String>() {
  4. @Override
  5. public String apply(Author author) {
  6. return author.getName();
  7. }
  8. })
  9. .forEach(item -> System.out.println(item));

通过Stream Trace工具可以直观的感受到
image.png
我们也可以对流中的元素进行计算,例如:我们需要将集合中所有作者的年龄 + 10

  1. List<Author> authors = getAuthors();
  2. authors.stream()
  3. .map( author -> author.getAge())
  4. .map( age -> age + 10)
  5. .forEach( item -> System.out.println(item));

2.3.3 distinct方法

可以去除流中的重复元素。distinct方法是依赖Objectequals方法来判断是否是相同对象的。所以需要注意重写equals方法。

注意: 如果我们使用了Lombok插件,那么我们可以直接通过@Data注解来帮我们生成equals方法

  1. List<Author> authors = getAuthors();
  2. authors.stream()
  3. .distinct()
  4. .forEach(item -> System.out.println(item.getName()));

2.3.4 sorted方法

可以对流中的元素进行排序。

  1. List<Author> authors = getAuthors();
  2. authors.stream()
  3. .distinct()
  4. .sorted()
  5. .forEach(author -> System.out.println(author.getAge()));

注意: 该方法会返回由该流的元素组成的流,按自然顺序排序。如果该流的元素不是Comparable,则在执行终端操作时可能会抛出java.lang.ClassCastException, 所以我们需要在实体类对象中实现Comparable接口,并重写compareTo()方法

我们也可以使用这个带有参数的sorted()方法,重写一个compare()方法即可。

  1. List<Author> authors = getAuthors();
  2. authors.stream()
  3. .distinct()
  4. .sorted(((o1, o2) -> o2.getAge() - o1.getAge()))
  5. .forEach(author -> System.out.println(author.getAge()));

2.3.5 limit方法

可以设置流的最大长度,超出的部分将被抛弃。

  1. List<Author> authors = getAuthors();
  2. authors.stream()
  3. .limit(2)
  4. .forEach(author -> System.out.println(author));

2.3.6 skip方法

跳过流中的前n个元素,返回剩下的元素

  1. List<Author> authors = getAuthors();
  2. authors.stream()
  3. .skip(2)
  4. .forEach(author -> System.out.println(author));

2.3.7 flatMap方法

map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素。

  1. List<Author> authors = getAuthors();
  2. authors.stream()
  3. .flatMap(author -> author.getBooks().stream())
  4. .distinct()
  5. .forEach(author -> System.out.println(author.getName()));

image.png