zoukankan      html  css  js  c++  java
  • Java1.8之Lambda表达式、流Stream学习

    1、什么是函数式编程?

    答:每个人对函数式编程的理解不尽相同。但其核心是:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另一个值。

    2、Java 8的最大变化是引入了Lambda表达式——一种紧凑的、传递行为的方式。

    答:和使用匿名内部类的另一处不同在于声明参数的方式。使用匿名内部类时需要显式地声明参数类型,而在Lambda表达式中无需指定类型,程序依然可以编译。这是因为javac根据程序的上下文在后台推断出了参数的类型。这意味着如果参数类型不言而明,则无需显式指定。

      尽管与之前相比,Lambda表达式中的参数需要的样板代码很少,但是Java 8仍然是一种静态类型语言。为了增加可读性并迁就我们的习惯,声明参数时也可以包括类型信息,而且有时编译器不一定能根据上下文推断出参数的类型!

      注意:->符号将参数和Lambda表达式的主体分开。

    3、Java8之Lambda的简单案例使用,如下所示:

     1 package com.demo.main;
     2 
     3 import java.awt.event.ActionListener;
     4 import java.util.function.BinaryOperator;
     5 
     6 public class LambdaMain {
     7 
     8     // 目标类型是指Lambda表达式所在上下文环境的类型。
     9     // 比如,将Lambda表达式赋值给一个局部变量,或传递给一个方法作为参数,局部变量或方法参数的类型就是Lambda表达式的目标类型。
    10     public static void main(String[] args) {
    11         // Lambda表达式的不同形式
    12         // 1、方式一,Lambda表达式不包含参数,使用空括号()表示没有参数。
    13         // 该Lambda表达式实现了Runnable接口,该接口也只有一个run方法,没有参数,且返回类型为void。
    14         Runnable noArguments = () -> System.out.println("方式一,hello Lambda!!!");
    15         noArguments.run();
    16 
    17         // 2、方式二,Lambda表达式包含且只包含一个参数,可省略参数的括号
    18         ActionListener oneArgument = event -> System.out.println("方式二,button clicked !!!");
    19 
    20         // 3、方式三,Lambda表达式的主体不仅可以是一个表达式,而且也可以是一段代码块,使用大括号({})将代码块括起来
    21         Runnable multiStatement = () -> {
    22             System.out.println("方式三,hello Lambda first !!!");
    23             System.out.println("方式三,hello Lambda second!!!");
    24         };
    25         multiStatement.run();
    26 
    27         // 4、方式四,Lambda表达式也可以表示包含多个参数的方法。
    28         // 这行代码并不是将两个数字相加,而是创建了一个函数,用来计算两个数字相加的结果。
    29         // 变量add的类型是BinaryOperator<Long>,它不是两个数字的和,而是将两个数字相加的那行代码。
    30         BinaryOperator<Long> add = (x, y) -> x + y;
    31         System.out.println("方式四,add : " + add.apply(2L, 3L));
    32 
    33         // 5、方式五,有时最好也可以显式声明参数类型,此时就需要使用小括号将参数括起来,多个参数的情况也是如此
    34         BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
    35         System.out.println("方式五,addExplicit : " + addExplicit.apply(1L, 2L));
    36 
    37     }
    38 
    39 }

    4、Java的函数接口?

    答:函数接口是只有一个抽象方法的接口,用作Lambda表达式的类型。

     1 package com.demo.main;
     2 
     3 public interface LambdaType<T> {
     4 
     5     // 函数接口是只有一个抽象方法的接口,用作Lambda表达式的类型。
     6     abstract int add(T x,T y);
     7     
     8     public static void main(String[] args) {
     9         LambdaType<Integer> lambdaType =  (x, y) -> x + y;
    10         System.out.println(lambdaType.add(1, 2));
    11     }
    12     
    13 }

    5、Java8的Lambda要点内容:

    答:1)、Lambda表达式是一个匿名方法,将行为像数据一样进行传递。

      2)、Lambda表达式的常见结构: BinaryOperator<Integer> add=(x, y) → x+y。

      3)、函数接口指仅具有单个抽象方法的接口,用来表示Lambda表达式的类型。

    6、Stream是用函数式编程方式在集合类上进行复杂操作的工具。

    答:1)、Stream里的一些方法却略有不同,它们虽是普通的Java方法,但返回的Stream对象却不是一个新集合,而是创建新集合的配方。

      2)、像filter这样只描述Stream,最终不产生新集合的方法叫作惰性求值方法,而像count这样最终会从Stream产生值的方法叫作及早求值方法。

      3)、判断一个操作是惰性求值还是及早求值很简单:只需看它的返回值。如果返回值是Stream,那么是惰性求值;如果返回值是另一个值或为空,那么就是及早求值。使用这些操作的理想方式就是形成一个惰性求值的链,最后用一个及早求值的操作返回想要的结果,这正是它的合理之处。

     1 package com.demo.main;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Iterator;
     5 import java.util.List;
     6 import java.util.stream.Stream;
     7 
     8 public class StramMain {
     9 
    10     public static void main(String[] args) {
    11         List<String> lists = new ArrayList<String>();
    12         lists.add("Java");
    13         lists.add("SpringCloud");
    14         lists.add("SpringBoot");
    15         lists.add("Spring");
    16 
    17         // 习惯写法一
    18         for (String str : lists) {
    19             if (str.contains("Spring")) {
    20                 System.out.println("for循环:" + str.toString());
    21             }
    22         }
    23         System.out.println();
    24 
    25         // 习惯写法二,方法是返回一个控制迭代的Iterator对象
    26         Iterator<String> iterator = lists.iterator();
    27         while (iterator.hasNext()) {
    28             String str = iterator.next();
    29             if (str.contains("Spring")) {
    30                 System.out.println("while循环:" + str.toString());
    31             }
    32         }
    33         System.out.println();
    34 
    35         // Java8流式写法,stream()方法的调用,返回内部迭代中的相应接口:Stream。
    36         long count = lists.stream().filter(list -> {
    37             System.out.println("filter是惰性求值方法");
    38             return list.contains("Spring");
    39         }).count();
    40         System.out.println("count及早求值方法: " + count);
    41         
    42     }
    43 
    44 }

    7、Stream常用的流操作。

    答:1)、collect(toList())方法由Stream里的值生成一个列表,是一个及早求值操作。

      2)、Stream的of方法使用一组初始值生成新的Stream。

     1 package com.demo.main;
     2 
     3 import java.util.List;
     4 import java.util.stream.Collectors;
     5 import java.util.stream.Stream;
     6 
     7 public class StramMain {
     8 
     9     public static void main(String[] args) {
    10         // Stream<String> list = Stream.of("Spring", "SpringBoot", "SpringCloud");
    11         // List<String> collected = list.collect(Collectors.toList());
    12         // 可以缩写为下面一句
    13         List<String> collected = Stream.of("Spring", "SpringBoot", "SpringCloud").collect(Collectors.toList());
    14 
    15         // 使用流Stream进行遍历操作,可以直接打印信息
    16         collected.forEach((String str) -> System.out.println(str.toString()));
    17         // 省略Lanbda的参数类型
    18         collected.forEach(str -> System.out.println(str.toString()));
    19     }
    20 
    21 }

      3)、map如果有一个函数可以将一种类型的值转换成另外一种类型,map操作就可以使用该函数,将一个流中的值转换成一个新的流。

     1 package com.demo.main;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Arrays;
     5 import java.util.List;
     6 import java.util.stream.Collectors;
     7 import java.util.stream.Stream;
     8 
     9 public class StramMain {
    10 
    11     public static void main(String[] args) {
    12         // 习惯写法,使用for循环将字符串转换为大写
    13         List<String> list = new ArrayList<String>();
    14         for (String str : Arrays.asList("Spring", "SpringBoot", "SpringCloud")) {
    15             String upperStr = str.toUpperCase();
    16             list.add(upperStr);
    17         }
    18 
    19         // Stream流式写法,使用map操作将字符串转换为大写形式
    20         Stream<String> stream = Stream.of("Spring", "SpringBoot", "SpringCloud").map(str -> str.toUpperCase());
    21         List<String> collected = stream.collect(Collectors.toList());
    22         collected.forEach(str -> System.out.println(str.toString()));
    23         System.out.println();
    24 
    25         // 一句写法
    26         Stream.of("Spring", "SpringBoot", "SpringCloud")
    27                 // 传给map的Lambda表达式只接受一个String类型的参数,返回一个新的String类型。
    28                 .map(str -> str.toUpperCase()) 
    29                 // 参数和返回值不必属于同一种类型,但是Lambda表达式必须是Function接口的一个实例,
    30                 // Function接口是只包含一个参数的普通函数接口。
    31                 .collect(Collectors.toList())
    32                 .forEach(str -> System.out.println(str.toString()));
    33 
    34     }
    35 
    36 }

    4)、filter遍历数据并检查其中的元素时,可尝试使用Stream中提供的新方法filter。 

     1 package com.demo.main;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Arrays;
     5 import java.util.List;
     6 import java.util.stream.Collectors;
     7 import java.util.stream.Stream;
     8 
     9 public class StramMain {
    10 
    11     public static void main(String[] args) {
    12         // 习惯写法,使用循环遍历列表,使用条件语句做判断
    13         List<String> list = new ArrayList<String>();
    14         for (String str : Arrays.asList("Spring", "SpringBoot", "SpringCloud")) {
    15             if (str.startsWith("Spring")) {
    16                 list.add(str);
    17             }
    18         }
    19         // 这里使用流式遍历
    20         list.stream().forEach(str -> System.out.println(str.toString()));
    21         System.out.println();
    22 
    23         // Stream流式写法,使用循环遍历列表,使用条件语句做判断
    24         Stream<String> stream = Stream.of("Spring", "SpringBoot", "SpringCloud")
    25                 .filter(str -> str.startsWith("Spring"));
    26         List<String> collected = stream.collect(Collectors.toList());
    27         collected.forEach(str -> System.out.println(str.toString()));
    28         System.out.println();
    29         
    30         // Stream一句写法
    31         Stream.of("Spring", "SpringBoot", "SpringCloud")
    32                 // 和map很像,filter接受一个函数(函数接口)作为参数,该函数用Lambda表达式表示。
    33                 .filter(str -> str.startsWith("Spring"))
    34                 .collect(Collectors.toList())
    35                 .forEach(str -> System.out.println(str.toString()));
    36         
    37     }
    38 
    39 }

    5)、flatMap方法可用Stream替换值,然后将多个Stream连接成一个Stream。map操作,它可用一个新的值代替Stream中的值。但有时,如果希望让map操作有点变化,生成一个新的Stream对象取而代之。用户通常不希望结果是一连串的流,此时flatMap最能派上用场。

     1 package com.demo.main;
     2 
     3 import java.util.Arrays;
     4 import java.util.List;
     5 import java.util.stream.Collectors;
     6 import java.util.stream.Stream;
     7 
     8 public class StramMain {
     9 
    10     public static void main(String[] args) {
    11         // 习惯写法,使用循环遍历列表,使用条件语句做判断
    12 
    13         // Stream流式写法,使用循环遍历列表,使用条件语句做判断
    14         Stream<List<String>> stream = Stream.of(Arrays.asList("Spring"), Arrays.asList("SpringBoot", "SpringCloud"));
    15         Stream<String> flatMap = stream.flatMap(list -> list.stream());
    16         List<String> list = flatMap.collect(Collectors.toList());
    17         list.forEach(str -> System.out.println(str.toString()));
    18         System.out.println();
    19         
    20         // Stream一句写法
    21         Stream.of(Arrays.asList("Spring"), Arrays.asList("SpringBoot", "SpringCloud"))
    22                 .flatMap(list2 -> list2.stream())
    23                 .collect(Collectors.toList())
    24                 .forEach(str -> System.out.println(str.toString()));
    25     }
    26 
    27 }

    6)、Stream上常用的操作之一是求最大值和最小值。Stream API中的max和min操作足以解决这一问题。

     1 package com.demo.main;
     2 
     3 import java.util.Arrays;
     4 import java.util.Comparator;
     5 import java.util.List;
     6 import java.util.Optional;
     7 
     8 public class StramMain {
     9 
    10     public static void main(String[] args) {
    11         List<BookInfo> list = Arrays.asList(new BookInfo("Spring", 100), new BookInfo("SpringBoot", 200),
    12                 new BookInfo("SpringCloud", 300));
    13 
    14         // 习惯写法,使用循环遍历列表,使用条件语句做判断
    15         BookInfo bookInfo = list.get(0);
    16         for (BookInfo book : list) {
    17             if (book.getPrice() < bookInfo.getPrice()) {
    18                 bookInfo = book;
    19             }
    20         }
    21         System.out.println(bookInfo.toString());
    22         System.out.println();
    23 
    24         // Stream流式写法,使用循环遍历列表,使用条件语句做判断
    25         Optional<BookInfo> optionalMin = list.stream().min(Comparator.comparing(BookInfo::getPrice));
    26         BookInfo bookStreamMin = optionalMin.get();
    27         System.out.println(bookStreamMin.toString());
    28         System.out.println();
    29 
    30         // Stream一句写法
    31         // 取出最小值
    32         BookInfo bookStreamMin2 = list.stream().min(Comparator.comparing(BookInfo::getPrice)).get();
    33         System.out.println(bookStreamMin2.toString());
    34         System.out.println();
    35 
    36         // 取出最大值
    37         BookInfo bookStreamMax = list.stream().max(Comparator.comparing(BookInfo::getPrice)).get();
    38         System.out.println(bookStreamMax.toString());
    39         System.out.println();
    40 
    41 //        java1.8的双冒号(::),双冒号(::)运算符在Java 8中被用作方法引用(method reference),方法引用是与lambda表达式相关的一个重要特性。它提供了一种不执行方法的方法。为此,方法引用需要由兼容的函数接口组成的目标类型上下文。
    42 //        大致意思是,使用lambda表达式会创建匿名方法, 但有时候需要使用一个lambda表达式只调用一个已经存在的方法(不做其它), 所以这才有了方法引用!
    43 
    44 //        以下是Java 8中方法引用的一些语法:
    45 //        1)、静态方法引用(static method)语法:classname::methodname 例如:Person::getAge
    46 //        2)、对象的实例方法引用语法:instancename::methodname 例如:System.out::println
    47 //        3)、对象的超类方法引用语法: super::methodname
    48 //        4)、类构造器引用语法: classname::new 例如:ArrayList::new
    49 //        5)、数组构造器引用语法: typename[]::new 例如: String[]:new
    50         
    51     }
    52 
    53 }

    7)、reduce操作可以实现从一组值中生成一个值。如count、min和max方法,因为常用而被纳入标准库中。事实上,这些方法都是reduce操作。

     1 package com.demo.main;
     2 
     3 import java.util.Arrays;
     4 import java.util.function.BinaryOperator;
     5 import java.util.stream.Stream;
     6 
     7 public class StramMain {
     8 
     9     public static void main(String[] args) {
    10         // 习惯写法,使用命令式编程方式求和
    11         int sum = 0;
    12         for (Integer nums : Arrays.asList(1, 2, 3, 4)) {
    13             sum = sum + nums;
    14         }
    15         System.out.println("sum : " + sum);
    16 
    17         // Stream流式写法,使用reduce求和
    18         // Lambda表达式的返回值是最新的sum2。
    19         // Lambda表达式就是reducer,它执行求和操作,有两个参数:传入Stream中的当前元素num2和sum2。将两个参数相加,sum2是累加器,保存着当前的累加结果。
    20         BinaryOperator<Integer> accumulator = (acc, element) -> acc + element;
    21         int count = accumulator.apply(accumulator.apply(accumulator.apply(accumulator.apply(0, 1), 2), 3), 4);
    22         System.out.println("count: " + count);
    23 
    24         // Stream一句写法
    25         Integer sumStream = Stream.of(1, 2, 3, 4).reduce(0, (sum2, num2) -> sum2 + num2);
    26         System.out.println("sumStream : " + sumStream);
    27 
    28     }
    29 
    30 }

    8)、综合案例,如何根据图书列表,找出图书所属的公司团队,如下所属:

      1 package com.demo.main;
      2 
      3 import java.util.HashSet;
      4 import java.util.Set;
      5 import java.util.stream.Collectors;
      6 import java.util.stream.Stream;
      7 
      8 public class StramMain {
      9 
     10     private Set<BookInfo> getAllBookInfos() {
     11         Set<BookInfo> set = new HashSet<BookInfo>();
     12         // 维护图书集合
     13         set.add(new BookInfo("Spring", "Pivotal-1", 100));
     14         set.add(new BookInfo("SpringBoot", "Pivotal-2", 200));
     15         set.add(new BookInfo("SpringCloud", "Pivotal-3", 300));
     16         return set;
     17     }
     18 
     19     private Set<String> getAllBookNames() {
     20         Set<BookInfo> bookInfos = this.getAllBookInfos();
     21         Set<String> set = new HashSet<String>();
     22         // 遍历获取到图书名称
     23         for (BookInfo bookInfo : bookInfos) {
     24             set.add(bookInfo.getBookname());
     25         }
     26         return set;
     27     }
     28 
     29     public static void main(String[] args) {
     30         // 习惯写法
     31 
     32         // Stream流式写法,找出图书技术所属的公司
     33         StramMain stramMain = new StramMain();
     34         // 首先获取到所有的图书信息并过滤到自己想要的图书信息
     35         Stream<BookInfo> stream = stramMain.getAllBookInfos().stream()
     36                 .filter(bookInfo -> bookInfo.getBookname().startsWith("Spring"));
     37         // 使用map将技术图书映射为所属的公司
     38         Stream<String> streaMap = stream.map(bookInfo -> bookInfo.getTeam());
     39         // 使用collect(Collectors.toList())方法将图书所属的公司放入一个列表。
     40         Set<String> collect = streaMap.collect(Collectors.toSet());
     41         // 循环遍历输出
     42         collect.forEach(bookTeam -> System.out.println(bookTeam.toString()));
     43 
     44         // Stream一句写法
     45         // filter和map方法都返回Stream对象,因此都属于惰性求值,而collect方法属于及早求值。
     46         // List或Set这样的集合类,只要调用List或Set的stream方法就能得到一个Stream对象。
     47         stramMain.getAllBookInfos().stream()
     48                 .filter(bookInfo -> bookInfo.getBookname().startsWith("Spring"))
     49                 // map方法接受一个Lambda表达式,使用该Lambda表达式对Stream上的每个元素做映射,形成一个新的Stream。
     50                 .map(bookInfo -> bookInfo.getTeam())
     51                 .collect(Collectors.toSet())
     52                 .forEach(bookTeam -> System.out.println(bookTeam.toString()));
     53     }
     54 
     55     class BookInfo {
     56         private String bookname;
     57         private String team;
     58         private int price;
     59 
     60         public String getBookname() {
     61             return bookname;
     62         }
     63 
     64         public void setBookname(String bookname) {
     65             this.bookname = bookname;
     66         }
     67 
     68         public String getTeam() {
     69             return team;
     70         }
     71 
     72         public void setTeam(String team) {
     73             this.team = team;
     74         }
     75 
     76         public int getPrice() {
     77             return price;
     78         }
     79 
     80         public void setPrice(int price) {
     81             this.price = price;
     82         }
     83 
     84         @Override
     85         public String toString() {
     86             return "BookInfo [bookname=" + bookname + ", team=" + team + ", price=" + price + "]";
     87         }
     88 
     89         public BookInfo(String bookname, String team, int price) {
     90             super();
     91             this.bookname = bookname;
     92             this.team = team;
     93             this.price = price;
     94         }
     95 
     96         public BookInfo() {
     97             super();
     98         }
     99     }
    100 
    101 }

    8、如何使用Stream流和Lambda重构遗留代码。

      1 package com.demo.main;
      2 
      3 import java.util.HashSet;
      4 import java.util.Iterator;
      5 import java.util.Set;
      6 import java.util.stream.Collectors;
      7 
      8 public class StramMain {
      9 
     10     private Set<BookInfo> getAllBookInfos() {
     11         Set<BookInfo> set = new HashSet<BookInfo>();
     12         // 维护图书集合
     13         set.add(new BookInfo("Spring", "Pivotal-1", 100));
     14         set.add(new BookInfo("SpringBoot", "Pivotal-2", 200));
     15         set.add(new BookInfo("SpringCloud", "Pivotal-3", 300));
     16         return set;
     17     }
     18 
     19     private Set<String> getAllBookNames() {
     20         Set<BookInfo> bookInfos = this.getAllBookInfos();
     21         Set<String> set = new HashSet<String>();
     22         // 遍历获取到图书名称
     23         for (BookInfo bookInfo : bookInfos) {
     24             set.add(bookInfo.getBookname());
     25         }
     26         return set;
     27     }
     28 
     29     public static void main(String[] args) {
     30         StramMain stramMain = new StramMain();
     31         // 习惯写法,找出图书价格大于等于200的图书信息列表
     32         Set<BookInfo> seBookInfos = new HashSet<BookInfo>();
     33         for (BookInfo bookInfo : stramMain.getAllBookInfos()) {
     34             // 如果图书价格大于等于200
     35             if (bookInfo.getPrice() >= 200) {
     36                 seBookInfos.add(bookInfo);
     37             }
     38         }
     39         // 循环输出
     40         Iterator<BookInfo> iterator = seBookInfos.iterator();
     41         while (iterator.hasNext()) {
     42             System.out.println(iterator.next().toString());
     43         }
     44         System.out.println();
     45 
     46         
     47         
     48         // Stream流式写法,找出图书价格大于等于200的图书信息列表
     49         Set<BookInfo> bookInfoStream = new HashSet<BookInfo>();
     50         stramMain.getAllBookInfos().stream().forEach(bookInfo -> {
     51             if (bookInfo.getPrice() >= 200) {
     52                 bookInfoStream.add(bookInfo);
     53             }
     54         });
     55         bookInfoStream.forEach(bookInfo -> System.out.println(bookInfo.toString()));
     56         System.out.println();
     57 
     58         
     59         
     60         // Stream一句写法,找出图书价格大于等于200的图书信息列表
     61         Set<BookInfo> bookInfoStream2 = new HashSet<BookInfo>();
     62         stramMain.getAllBookInfos().stream()
     63                 // 找出满足图书价格大于200的
     64                 .filter(bookInfo -> bookInfo.getPrice() >= 200)
     65                 // 将满足条件的图书列表生成一个新的Stream流
     66                 .map(bookInfo -> bookInfo)
     67                 // 使用循环将新生成的流Stream循环遍历到Set集合中
     68                 .forEach(bookInfo -> bookInfoStream2.add(bookInfo));
     69         // 循环遍历输出
     70         bookInfoStream2.forEach(bookInfo -> System.out.println(bookInfo.toString()));
     71         System.out.println();
     72         
     73         
     74         
     75         // Stream一句写法,找出图书价格大于等于200的图书信息列表
     76         // 使用collect(Collectors. toList())可以将Stream中的值转换成一个列表,
     77         // 使用collect(Collectors.toSet())可以将Stream中的值转换成一个集合。
     78         stramMain.getAllBookInfos().stream()
     79             // 找出满足图书价格大于200的
     80             .filter(bookInfo -> bookInfo.getPrice() >= 200)
     81             // 将满足条件的图书列表生成一个新的Stream流
     82             .map(bookInfo -> bookInfo)
     83             // 将生成的stream流转换为set集合
     84             .collect(Collectors.toSet())
     85             .forEach(bookInfo -> System.out.println(bookInfo.toString()));;
     86             
     87     }
     88 
     89     class BookInfo {
     90         private String bookname;
     91         private String team;
     92         private int price;
     93 
     94         public String getBookname() {
     95             return bookname;
     96         }
     97 
     98         public void setBookname(String bookname) {
     99             this.bookname = bookname;
    100         }
    101 
    102         public String getTeam() {
    103             return team;
    104         }
    105 
    106         public void setTeam(String team) {
    107             this.team = team;
    108         }
    109 
    110         public int getPrice() {
    111             return price;
    112         }
    113 
    114         public void setPrice(int price) {
    115             this.price = price;
    116         }
    117 
    118         @Override
    119         public String toString() {
    120             return "BookInfo [bookname=" + bookname + ", team=" + team + ", price=" + price + "]";
    121         }
    122 
    123         public BookInfo(String bookname, String team, int price) {
    124             super();
    125             this.bookname = bookname;
    126             this.team = team;
    127             this.price = price;
    128         }
    129 
    130         public BookInfo() {
    131             super();
    132         }
    133     }
    134 
    135 }

    9、高阶函数是指接受另外一个函数作为参数,或返回一个函数的函数。高阶函数不难辨认:看函数签名就够了。如果函数的参数列表里包含函数接口,或该函数返回一个函数接口,那么该函数就是高阶函数。

     1 /**
     2      * Returns a stream consisting of the results of applying the given
     3      * function to the elements of this stream.
     4      *
     5      * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     6      * operation</a>.
     7      *
     8      * @param <R> The element type of the new stream
     9      * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
    10      *               <a href="package-summary.html#Statelessness">stateless</a>
    11      *               function to apply to each element
    12      * @return the new stream
    13      */
    14     <R> Stream<R> map(Function<? super T, ? extends R> mapper);

    10、Java 8中的另一个变化是引入了默认方法和接口的静态方法,它改变了人们认识类库的方式,接口中的方法也可以包含代码体了。

    答:1)、Java1.8的默认方法,如果子类未实现父接口的方法,则使用父接口里面的方法,这样的方法叫作默认方法,在任何接口中,无论函数接口还是非函数接口,都可以使用该方法。

      2)、和类不同,接口没有成员变量,因此默认方法只能通过调用子类的方法来修改子类本身,避免了对子类的实现做出各种假设。

    11、Java 8中的默认方法,理解:

    答:1)、类胜于接口。如果在继承链中有方法体或抽象的方法声明,那么就可以忽略接口中定义的方法。

      2)、子类胜于父类。如果一个接口继承了另一个接口,且两个接口都定义了一个默认方法,那么子类中定义的方法胜出。

      3)、如果上面两条规则不适用,子类要么需要实现该方法,要么将该方法声明为抽象方法。




     


     

     

     

  • 相关阅读:
    电源积累
    电感的分类及作用
    电容退耦原理分享
    电容选型
    上拉电阻
    LVTTL与LVCMOS区别
    可重入函数与不可重入函数
    永不改变的PCB设计黄金法则
    os_cpu_a.asm
    [原创]Getting Started with Skywalking
  • 原文地址:https://www.cnblogs.com/biehongli/p/14207672.html
Copyright © 2011-2022 走看看