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



 


 


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!