zoukankan      html  css  js  c++  java
  • 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<T,R>:有输入,有输出
     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<String, Integer> 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<T, R> 抽象方法 R apply(T t);
    30     private static Integer testFunction(String str, Function<String, Integer> function) {
    31         // str作为第13行的参数s进行传递
    32         return function.apply(str);
    33     }
    34 }

     结果

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

    2.1 函数型接口Function类型

      • 函数型接口Function<T,R>
        • 抽象方法 R apply(T t)
      • 消费型接口Consumer<T>
        •  抽象方法:void accept(T t)
      • 供给型接口Supplier<T>
        •  抽象方法:T get()
      • 断言型接口Predicate<T>
        •  抽象方法:boolean test(T t)
     1 package java8;
     2 
     3 import java.util.function.Function;
     4 
     5 /**
     6  * 1. 函数型接口Function<T,R>:有输入,有输出
     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<String, Integer> 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<T, R> 抽象方法 R apply(T t);
    30     private static Integer testFunction(String str, Function<String, Integer> 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<T> 消费性接口有输入,但是没有返回值
     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<String> consumer, String str) {
    17         consumer.accept(str);
    18     }
    19 }
     1 package java8;
     2 
     3 
     4 import java.util.function.Supplier;
     5 
     6 /**
     7  * Supplier<T> 供给型接口:无输入、有输出
     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<Person>的抽象方法get实现";
    17             System.out.println(name);
    18             return new Person(name);
    19         });
    20     }
    21 
    22     private static Person testSupplier(Supplier<Person> 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<T>
     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<Integer> predicate, int a) {
    23         return predicate.test(a);
    24     }
    25 }

    2.3 reduce

    https://www.cnblogs.com/flydean/p/java-8-stream-reduce.html

    https://www.liaoxuefeng.com/wiki/1252599548343744/1322402971648033

    https://blog.csdn.net/qq_33351091/article/details/82494855

     1 package mtee3rule;
     2 
     3 import java.util.Arrays;
     4 import java.util.List;
     5 import java.util.Optional;
     6 
     7 public class ReduceTest {
     8 
     9     public static void main(String[] args) {
    10         List<Integer> intList = Arrays.asList(1,2,3,4);
    11 
    12         Optional<Integer> result1 = intList.stream().reduce(Integer::sum);
    13         System.out.println("result1=" + result1 + ", sum=" + result1.get());
    14 
    15         Integer result2=intList.stream().reduce(100, Integer::sum);
    16         System.out.println("result2=" + result2 + ", sum=" + result2);
    17 
    18         // 每个线程的初始累加值都是100,最后4个线程加出来的结果就是406
    19         // 这里sum方法的identity只能是0。所以这里我们传入100是不对的,因为sum(100+1)!= 1。
    20         // 如果我们用0作为identity,则stream和parallelStream计算出的结果是一样的。这就是identity的真正意图。
    21         Integer result3=intList.parallelStream().reduce(100, Integer::sum);
    22         System.out.println("result3=" + result2 + ", sum=" + result3);
    23 
    24         testMultiReduce1();
    25     }
    26 
    27     private static void testMultiReduce1() {
    28         List<String> strings = Arrays.asList("1", "2", "4", "5");
    29 
    30         System.out.println("********in testMultiReduce1()************");
    31 
    32         // 非并行流
    33         Integer reduce1 = strings.stream().reduce(0,
    34                 (acc, e) -> acc + Integer.valueOf(e), (u, t) -> {
    35                     // 非并行流,不会执行第三个参数
    36                     System.out.println("u----:" + u);
    37                     // 这里的返回值并没有影响返回结果
    38                     return null;
    39                 });
    40         System.out.println("reduce1:" + reduce1);
    41 
    42         // 并行流
    43         //System.out.println("out_thread=" + Thread.currentThread().getName());
    44         Integer reduce2 = strings.parallelStream().reduce(0,
    45                 (acc, e) -> acc + Integer.valueOf(e), (u, t) -> {
    46                     // u,t分别为并行流每个子任务的结果
    47                     System.out.println("inner_thread=" + Thread.currentThread().getName() + ", u=" + u + ", t=" + t);
    48 
    49                     return u + t;
    50                 });
    51         System.out.println("out_thread=" + Thread.currentThread().getName());
    52         System.out.println("reduce2:" + reduce2);
    53     }
    54 
    55 }

    结果:

     1 result1=Optional[10], sum=10
     2 result2=110, sum=110
     3 result3=110, sum=410
     4 ********in testMultiReduce1()************
     5 reduce1:12
     6 inner_thread=ForkJoinPool.commonPool-worker-2, u=1, t=2    // 第一个线程执行
     7 inner_thread=main, u=4, t=5                                // 第二个线程执行
     8 inner_thread=main, u=3, t=9                                // u为第6行执行结果3,t为第7行执行结果9
     9 out_thread=main
    10 reduce2:12                                                 // 第8行执行结果 = 3 + 9

    2.4 创建Stream流的方式

     2.4.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<String> 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<String> 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<String> 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<String> listStr3 = Arrays.asList("adnm", "dn", "n");
    26         List<String> listStr4 = Arrays.asList("adnm", "w3", "3");
    27         Optional<String> optionalMax3 = listStr3.stream().max(String::indexOf);  // adnm.indexOf("dn")>0, "dn".indexOf("n")>0
    28         Optional<String> 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<String> optionalMax5 = listStr.stream().max((o1,o2) -> {return 1;});  // >=0:adnm 即两两比较 前面最大; <0,则最后一个最大
    32         System.out.println("optionalMax5=" + optionalMax5.get());  // max=adnm (第0个)
    33 
    34         Optional<String> 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<T>
    40          * comparing方法中需要一个函数型接口Function<T, R>,唯一的抽象方法为R apply(T t);
    41          * x作为Function方法的参数,到了Function方法体里 x作为对象来调用 无参数方法(这里x是String类型,则可以调用String的所有无参方法且返回值为int)
    42          */
    43         Optional<String> max1 = listStr.stream().max(Comparator.comparing((x) -> {
    44             return x.length();
    45         }));
    46         Optional<String> max2 = listStr.stream().max(Comparator.comparing((x) -> {
    47             return 1;
    48         }));
    49         Optional<String> 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<String> max1_1 = listStr.stream().max(Comparator.comparing(String::length));  // String::compareTo报错
    57         System.out.println("简写_最长的字符串 max1_1:" + max1_1.get());
    58     }
    59 }
    View Code

    结果:

    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

  • 相关阅读:
    web api中允许跨域访问
    HTTP Error 500.19
    使用SQL语句时应该注意的一些问题
    关于EsayUI中datagrid重复提交后台查询数据的问题
    EF6中使用事务的方法
    jquery中常用的方法和注意点
    在EF中正确的使用事务
    css解决移动端1px边框问题
    判定 JS 数据类型的最佳解决方案
    将伪数组转化为真数组
  • 原文地址:https://www.cnblogs.com/wxdlut/p/15560207.html
Copyright © 2011-2022 走看看