Java8新特性(Lambda表达式、Stream流、Optional类)等


1. Lambda表达式由来

 1 package java8;
 2 
 3 public class EmployeeTest {
 4     public static void main(String[] args) {
 5 
 6         Employee employee1 = new EmployeeImpl();
 7         employee1.getSalary();
 8         System.out.println("****************");
 9 
10 
11         Employee employee2 = new Employee() {
12             @Override
13             public void getSalary() {
14                 System.out.println("Employee匿名内部类");
15             }
16         };
17         employee2.getSalary();
18         System.out.println("****************");
19 
20         /**
21          * lambda表达式可以看作是一个接口的实例,使用lambda是有前提条件的,就是该接口必须是函数式接口。
22          * 那么什么是函数式接口呢?用一句话总结就是有且仅有一个抽象方法的接口(在java提供的类库中,函数式接口上面都有@FunctionalInterface注解)
23          *
24          * lambda表达式可以总结为:一个(), 一个 ->, 一段代码{}
25          * 一个():参数
26          * 一段代码{}:具体业务逻辑
27          */
28         Employee employee3 = () -> {
29             System.out.println("将上述匿名内部类转为使用lambda表达式");
30         };
31         employee3.getSalary();
32     }
33 
34     interface Employee {
35         public void getSalary();
36     }
37 
38     static class EmployeeImpl implements Employee {
39 
40         @Override
41         public void getSalary() {
42             System.out.print("Employee的普通实现类");
43         }
44     }
45 }

2. Stream流

2.1 函数型接口Function

 1 package java8;
 2 
 3 import java.util.function.Function;
 4 
 5 /**
 6  * 1. 函数型接口Function:有输入,有输出
 7  * 核心抽象方法为 抽象方法 R apply(T t);
 8  */
 9 public class FunctionInterface1 {
10 
11     public static void main(String[] args) {
12         // 通过lambda实例化一个接口,实现抽象方法R apply(T t);
13         Function function = (s) -> {
14             if (s == null) {
15                 return 0;
16             }
17             return s.length();
18         };
19         Integer result = testFunction("hello", function);
20         System.out.println(result);
21 
22         System.out.println("****************");
23         System.out.println(testFunction("hello", s -> {
24             return "更简化的写法".length();
25         }));
26     }
27 
28 
29     // interface Function 抽象方法 R apply(T t);
30     private static Integer testFunction(String str, Function function) {
31         // str作为第13行的参数s进行传递
32         return function.apply(str);
33     }
34 }

 结果

5
****************
6

2.1 函数型接口Function

    • 函数型接口Function
      • 抽象方法 R apply(T t)
    • 消费型接口Consumer
      •  抽象方法:void accept(T t)
    • 供给型接口Supplier
      •  抽象方法:T get()
    • 断言型接口Predicate
      •  抽象方法:boolean test(T t)
 1 package java8;
 2 
 3 import java.util.function.Function;
 4 
 5 /**
 6  * 1. 函数型接口Function:有输入,有输出
 7  * 核心抽象方法为 抽象方法 R apply(T t);
 8  */
 9 public class FunctionInterface1 {
10 
11     public static void main(String[] args) {
12         // 通过lambda实例化一个接口,实现抽象方法R apply(T t);
13         Function function = (s) -> {
14             if (s == null) {
15                 return 0;
16             }
17             return s.length();
18         };
19         Integer result = testFunction("hello", function);
20         System.out.println(result);
21 
22         System.out.println("****************");
23         System.out.println(testFunction("hello", s -> {
24             return "更简化的写法".length();
25         }));
26     }
27 
28 
29     // interface Function 抽象方法 R apply(T t);
30     private static Integer testFunction(String str, Function function) {
31         // str作为第13行的参数s进行传递
32         return function.apply(str);
33     }
34 }
 1 package java8;
 2 
 3 import java.util.function.Consumer;
 4 
 5 /**
 6  * Consumer 消费性接口有输入,但是没有返回值
 7  *     抽象方法:void accept(T t);
 8  */
 9 public class ConsuerFunctionInterface {
10 
11     public static void main(String[] args) {
12         // s是实例化方法accept的参数,{}内部是accept的方法体
13         testConsumer(s -> {System.out.println(s);}, "消费性接口抽象方法accept实现");
14     }
15 
16     private static void testConsumer(Consumer consumer, String str) {
17         consumer.accept(str);
18     }
19 }
 1 package java8;
 2 
 3 
 4 import java.util.function.Supplier;
 5 
 6 /**
 7  * Supplier 供给型接口:无输入、有输出
 8  *     抽象方法:T get();
 9  */
10 public class SupplierFunctionInterface {
11 
12     public static void main(String[] args) {
13 
14         // ()是实例化方法T get()参数:即无参数,{}是get的方法体
15         testSupplier(()-> {
16             String name = "Supplier的抽象方法get实现";
17             System.out.println(name);
18             return new Person(name);
19         });
20     }
21 
22     private static Person testSupplier(Supplier supplier) {
23         return supplier.get();
24     }
25 
26 }
27 
28 class Person {
29     private static String name;
30 
31     Person(String name) {
32         this.name = name;
33     }
34 }
 1 package java8;
 2 
 3 import java.util.function.Predicate;
 4 
 5 /**
 6  * 断言型接口Predicate
 7  *     抽象方法:boolean test(T t);
 8  */
 9 public class PredicateFunctionInterface {
10 
11     public static void main(String[] args) {
12         // b是test方法的参数, {}内部是test方法体
13         boolean res = testPredicate((b) -> {
14             System.out.println("断言型接口Predicate抽象方法boolean test(T t)的实例化");
15             return b > 99;
16         }, 99);
17 
18         System.out.println("b>99, res=" + res);
19     }
20 
21 
22     private static boolean testPredicate(Predicate predicate, int a) {
23         return predicate.test(a);
24     }
25 }

2.2 创建Stream流的方式

 2.2.1 ::(双冒号)使用

https://www.jianshu.com/p/96b4815d629e

 1 package java8;
 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 DoubleMaoHao {
 9 
10     public static void main(String[] args) {
11         List listStr = Arrays.asList("adnm", "p", "admmt", "pot", "xbangd", "weoujgsd");
12 
13         // 最大的串:实例化Comparator的抽象方法int compare(T o1, T o2)
14         // (o1, o2)有两个参数,o1作为当前对象,o2作为参数,都是String;返回值为int —— 其它方法满足这样条件的也可以
15         Optional optionalMax1 = listStr.stream().max(((o1, o2) -> { return o1.compareTo(o2);} ));
16 
17         // 简写
18         // 而String::compareTo方法是指int compareTo(String anotherString)--即参数为string,返回值为int的
19         // 其它方法 public int indexOf(String str) --即参数为string,返回值为int的 也可以,但是int length() 无参数的方法就不行
20         Optional optionalMax2 = listStr.stream().max(String::compareTo);  // String::length报错
21 
22         System.out.println("optionalMax1=" + optionalMax1.get() + ", optionalMax2=" + optionalMax2.get());  // optionalMax3=adnm, optionalMax4=w3
23 
24 
25         List listStr3 = Arrays.asList("adnm", "dn", "n");
26         List listStr4 = Arrays.asList("adnm", "w3", "3");
27         Optional optionalMax3 = listStr3.stream().max(String::indexOf);  // adnm.indexOf("dn")>0, "dn".indexOf("n")>0
28         Optional optionalMax4 = listStr4.stream().max(String::indexOf); // adnm.indexOf("w3")<0, "w3".indexOf("3")>0
29         System.out.println("optionalMax3=" + optionalMax3.get() + ", optionalMax4=" + optionalMax4.get());  // optionalMax3=adnm, optionalMax4=w3
30 
31         Optional optionalMax5 = listStr.stream().max((o1,o2) -> {return 1;});  // >=0:adnm 即两两比较 前面最大; <0,则最后一个最大
32         System.out.println("optionalMax5=" + optionalMax5.get());  // max=adnm (第0个)
33 
34         Optional optionalMax6 = listStr.stream().max((o1,o2) -> {return -1;});  // >=0:adnm 即两两比较 前面最大; <0,则最后一个最大
35         System.out.println("optionalMax6=" + optionalMax6.get());  // max=weoujgsd (最后一个)
36 
37 
38         /**
39          * max()方法中需要一个函数式接口Comparator
40          * comparing方法中需要一个函数型接口Function,唯一的抽象方法为R apply(T t);
41          * x作为Function方法的参数,到了Function方法体里 x作为对象来调用 无参数方法(这里x是String类型,则可以调用String的所有无参方法且返回值为int)
42          */
43         Optional max1 = listStr.stream().max(Comparator.comparing((x) -> {
44             return x.length();
45         }));
46         Optional max2 = listStr.stream().max(Comparator.comparing((x) -> {
47             return 1;
48         }));
49         Optional max3 = listStr.stream().max(Comparator.comparing((x) -> {
50             return -1;
51         }));
52         // 要看comparing内部的实现Function keyExtractor  (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
53         System.out.println("max1=" + max1.get() + ", max2=" + max2.get() + ", max3=" + max3.get());  // max1=weoujgsd, max2=adnm, max3=adnm
54 
55         // 简写形式——使用了静态方法Comparator.comparing,比较的是length属性,
56         Optional max1_1 = listStr.stream().max(Comparator.comparing(String::length));  // String::compareTo报错
57         System.out.println("简写_最长的字符串 max1_1:" + max1_1.get());
58     }
59 }

结果:

optionalMax1=xbangd, optionalMax2=xbangd
optionalMax3=adnm, optionalMax4=w3
optionalMax5=adnm
optionalMax6=weoujgsd
max1=weoujgsd, max2=adnm, max3=adnm
简写_最长的字符串 max1_1:weoujgsd

参考文献:

1.https://zhuanlan.zhihu.com/p/340538961

2.https://blog.csdn.net/yczz/article/details/50896975

3.https://blog.csdn.net/love905661433/article/details/86422169