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)、如果上面两条规则不适用,子类要么需要实现该方法,要么将该方法声明为抽象方法。




     


     

     

     

  • 相关阅读:
    USACO 3.3 A Game
    USACO 3.3 Camelot
    USACO 3.3 Shopping Offers
    USACO 3.3 TEXT Eulerian Tour中的Cows on Parade一点理解
    USACO 3.3 Riding the Fences
    USACO 3.2 Magic Squares
    USACO 3.2 Stringsobits
    USACO 3.2 Factorials
    USACO 3.2 Contact
    USACO 3.1 Humble Numbers
  • 原文地址:https://www.cnblogs.com/biehongli/p/14207672.html
Copyright © 2011-2022 走看看