首页 > 其他分享 >2022.11.11 方法引用与lambda并行流

2022.11.11 方法引用与lambda并行流

时间:2022-11-11 14:00:23浏览次数:61  
标签:11 map String author age authors 方法 2022.11 lambda

6. 方法引用

我们在使用lambda时,如果方法体中只有一个方法的调用的话(包括构造方法),我们可以用方法引用进一步简化代码。

6.1 推荐用法

我们在使用lambda时不需要考虑什么时候用方法引用,用哪种方法引用,方法引用的格式是什么。我们只需要在写完lambda方法发现方法体只有一行代码,并且是方法的调用(a.get())时使用快捷键尝试是否能够转换成方法引用即可。

当我们方法引用使用的多了慢慢的也可以直接写出方法引用。

6.2 基本格式

类名或者对象名::方法名

6.3 语法详解(了解)

6.3.1 引用类的静态方法

其实就是引用类的静态方法

格式
 类名::方法名

 

使用前提

如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个类的静态方法,并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个静态方法中,这个时候我们就可以引用类的静态方法。

例如:

如下代码就可以用方法引用进行简化

 List<Author> authors = getAuthors();
 Stream<Author> authorStream = authors.stream();
 authorStream.map(author -> author.getAge())
    .map(new Function<Integer, String>() {
         @Override
         //参数age 传入了静态方法String.valueOf()中
         public String apply(Integer age) {
             //一行代码,调用类的静态方法
             return String.valueOf(age);
        }
    });
 ​
 //将map转化为方法引用
 List<Author> authors = getAuthors();
 Stream<Author> authorStream = authors.stream();
 authorStream.map(author -> author.getAge())
    .map(String::valueOf);//类名::方法名

注意,如果我们所重写的方法是没有参数的,调用的方法也是没有参数的也相当于符合以上规则。

优化后如下:

         List<Author> authors = getAuthors();
 ​
         Stream<Author> authorStream = authors.stream();
 ​
         authorStream.map(author -> author.getAge())
                .map(String::valueOf);//类名::方法名

 

6.3.2 引用对象的实例方法

格式
 对象名::方法名
使用前提

如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个对象的成员方法,并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个成员方法中,这个时候我们就可以引用对象的实例方法

例如:

 List<Author> authors = getAuthors();
 ​
 Stream<Author> authorStream = authors.stream();
 StringBuffer sb = new StringBuffer();
 authorStream.map(author -> author.getAge())
    .forEach(new Consumer<Integer>() {
         @Override
         public void accept(Integer name) {
             // 调用对象的成员方法并且参数都传递了
             sb.append(name);
        }
    });

优化后:

 List<Author> authors = getAuthors();
 ​
 Stream<Author> authorStream = authors.stream();
 StringBuilder sb = new StringBuilder();
 authorStream.map(author -> author.getName())
    .forEach(sb::append);//对象名::方法名

6.3.4 引用类的实例方法

格式
 类名::方法名
使用前提

如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了第一个参数的成员方法,并且我们把要重写的抽象方法中剩余的所有的参数都按照顺序传入了这个成员方法中,这个时候我们就可以引用类的实例方法。

例如:

     interface UseString{
         String use(String str,int start,int length);
    }
 ​
     public static String subAuthorName(String str, UseString useString){
         int start = 0;
         int length = 1;
         return useString.use(str,start,length);
    }
     public static void main(String[] args) {
 ​
         subAuthorName("三更草堂", new UseString() {
             @Override
             public String use(String str, int start, int length) {
                 //调用了第一个参数的成员方法 剩余的参数都传入了方法中
                 return str.substring(start,length);
            }
        });
 ​
    }

优化后如下:

     interface UseString{
         String use(String str,int start,int length);
    }
 ​
     public static String subAuthorName(String str, UseString useString){
         int start = 0;
         int length = 1;
         return useString.use(str,start,length);
    }
     public static void main(String[] args) {
         subAuthorName("三更草堂", String::substring);//类名::成员方法
    }

6.3.5 构造器引用

如果方法体中的一行代码是构造器的话就可以使用构造器引用。

格式
 类名::new
使用前提

如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个类的构造方法,并且我们把要重写的抽象方法中的所有的参数都按照顺序传入了这个构造方法中,这个时候我们就可以引用构造器。

例如:

 List<Author> authors = getAuthors();
 authors.stream()
    .map(author -> author.getName())
    .map(new Function<String, StringBuilder>() {
         @Override
         public StringBuilder apply(String name) {
             //调用构造器 把apply方法的参数都传入了构造器
             return new StringBuilder(name);
        }
    })
    .map(sb->sb.append("-三更").toString())
    .forEach(str-> System.out.println(str));

优化后:

 List<Author> authors = getAuthors();
 authors.stream()
    .map(author -> author.getName())
    .map(StringBuilder::new)
    .map(sb->sb.append("-三更").toString())
    .forEach(str-> System.out.println(str));

7. 高级用法

基本数据类型优化

我们之前用到的很多Stream的方法由于都使用了泛型。所以涉及到的参数和返回值都是引用数据类型。

即使我们操作的是整数小数,但是实际用的都是他们的包装类。JDK5中引入的自动装箱和自动拆箱让我们在使用对应的包装类时就好像使用基本数据类型一样方便。但是你一定要知道装箱和拆箱肯定是要消耗时间的。虽然这个时间消耗很下。但是在大量的数据不断的重复装箱拆箱的时候,你就不能无视这个时间损耗了。

所以为了让我们能够对这部分的时间消耗进行优化。Stream还提供了很多专门针对基本数据类型的方法。

例如:mapToInt,mapToLong,mapToDouble,flatMapToInt,flatMapToDouble等。

     private static void test27() {
 ​
         List<Author> authors = getAuthors();
         authors.stream()
                .map(author -> author.getAge())//返回值为Integer
                .map(age -> age + 10)
                .filter(age->age>18)
                .map(age->age+2)
                .forEach(System.out::println);
 ​
         authors.stream()
                .mapToInt(author -> author.getAge())//返回值为int 省去了自动装箱拆箱的时间
                .map(age -> age + 10)
                .filter(age->age>18)
                .map(age->age+2)
                .forEach(System.out::println);
    }

 

并行流

当流中有大量元素时,我们可以使用并行流去提高操作的效率。其实并行流就是把任务分配给多个线程去完全。如果我们自己去用代码实现的话其实会非常的复杂,并且要求你对并发编程有足够的理解和认识。而如果我们使用Stream的话,我们只需要修改一个方法的调用就可以使用并行流来帮我们实现,从而提高效率。

parallel方法可以把串行流转换成并行流。

     private static void test28() {
         Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
         Integer sum = stream.parallel() //变为了并行流,后面的操作多线程完成
                .peek(new Consumer<Integer>() { //中间操作可以打印调试数据 forEach为终结操作
                     @Override
                     public void accept(Integer num) {
                         System.out.println(num+Thread.currentThread().getName());
                    }
                })
                .filter(num -> num > 5)
                .reduce((result, ele) -> result + ele)
                .get();
         System.out.println(sum);
    }

也可以通过parallelStream直接获取并行流对象。

         List<Author> authors = getAuthors();
         authors.parallelStream()//直接转化为并行流
                .map(author -> author.getAge())
                .map(age -> age + 10)
                .filter(age->age>18)
                .map(age->age+2)
                .forEach(System.out::println);
 

 

 

 
 

 

标签:11,map,String,author,age,authors,方法,2022.11,lambda
From: https://www.cnblogs.com/shanzha/p/16880274.html

相关文章

  • 2022.11.11 Lambda表达式
    2.Lambda表达式2.1概述Lambda是JDK8中一个语法糖。他可以对某些匿名内部类的写法进行简化。它是函数式编程思想的一个重要体现。让我们不用关注是什么对象。而是更关......
  • 2022.11.11 Stream流
    3.Stream流3.1概述Java8的Stream使用的是函数式编程模式,如同它的名字一样,它可以被用来对集合或数组进行链状流式的操作。可以更方便的让我们对集合或数组操作。 3.......
  • 2022.11.11 Optional
    4.Optional4.1概述我们在编写代码的时候出现最多的就是空指针异常。所以在很多情况下我们需要做各种非空的判断。例如: Authorauthor=getAuthor(); if(author!=n......
  • 1. 演进、环境与资源-20221111
    C++11也叫2.0了解:之前std:tr1的内容都已经放到std内了搜索:   :Gcc:unix家族,MinGW:windows家族   选择支持C++11还是14:【右击项目】–【选择属性】–【C/C++......
  • 11:高级部分-MySQL
    目录​​(一)view视图​​​​1.开场​​​​2.view视图创建、使用以及作用​​​​3.显示视图​​​​4.更新和删除视图​​​​5.视图算法:temptable,merge​​​​(......
  • Java Lambda 表达式
    目录​​一、说明​​​​二、理解​​​​三、演示​​​​1.常规方法实现​​​​2.静态内部类​​​​3.局部内部类​​​​4.匿名内部类​​​​5.Lambda表达式​​​​......
  • 2022-11-11 早报
    美国10月CPI带来重大惊喜,美股集体大幅收涨,纳指7.35%标普5.54%阿斯麦/英伟达14%亚马逊12%苹果/微软8%B站15%蔚来11%中芯国际Q3利润增46%蔚来Q3亏损增44%比特币上涨12%以太......
  • agv 地图 新 2022年11月11日08:45:44
    {"header":{"mapType":"2D-Map","mapName":"20221103161325514","minPos":{"x":-43.899,"y":-12.276......
  • [A202211110354]
    [A202211110354](2022,南开大学)设\(x_n=\displaystyle\sum_{k=0}^n{\frac{1}{k!}}\),\(n=1,2,\cdots\),求极限\[\lim_{n\rightarrow\infty}\left(\frac{\lnx_n}{\sqr......
  • [A202211110303]
    [A202211110303](2022,同济大学)已知\(\{a_n\}\)是一个实数列,\(0<|\lambda|<1\).证明:\(\displaystyle\lim_{n\rightarrow\infty}a_n=a\)的充要条件是\[\lim_{n\rig......