栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

一文掌握Lambda表达式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一文掌握Lambda表达式

目录

一、lambda基础知识

lambda语法

函数式接口

lambda与匿名内部类

方法引用 

二、 流计算

1.流与集合

2.构建流

2.1通过数组创建流

2.2通过集合类创建流

2.3创建持续流

3.流处理

3.1过滤

3.2映射

3.3调试

3.4排序

3.5去重

3.6截断

3.7匹配

3.8搜索

3.9汇聚

3.10收集

3.11副作用

总结


一、lambda基础知识

       

lambda语法

在Java语言中lambda表达式包含一个参数列表和一个lambda体,两者之间使用一个函数箭头"->"分割,如果有多个参数必须包围在括号中;如下文,表示入参数为x,y;求 x,y的和

(x,y)->x+y

函数式接口

       对于函数式接口实例的引用有效时就可以使用lambda表达式。什么是函数式接口呢?只有一个抽象方法的接口称为函数式接口

lambda与匿名内部类

  加入我们有一个数组[1,4,8],对这个数据进行排序;使用匿名内部类的实现方式如下:

   Arrays.asList(1,4,8).sort(new Comparator() {
            @Override
            public int compare(Integer a, Integer b) {
                return a.compareTo(b);
            }
        })

使用lambda表达式的实现则是:

        Arrays.asList(1,4,8).sort((a,b)->a.compareTo(b));

两者看起来很像,那么lambda是不是就是匿名内部类的语法糖呢?实际上两者之间还是有一些区别的

  1. 内部类的声明会创建一个新的命名作用域,在这个作用域中this指的是当前内部类实力;而lambda不会引入任何新的命名作用域。
  2. 内部类创建方式会确保创建一个拥有唯一标识的心对象,而lambda则不一定

方法引用 

 lambda有以下四种对现有类具名方法的引用

名字语法lambada示例
静态方法ClzName(arg)->ClzName.staticMethod(arg)
Arrays.asList(1,4,8).sort(Integer::compareTo);
绑定实例方法expr::instMethod(arg)->expr.instMethod(arg)list.forEach(System.out::println);
未绑定实例ClzName::instMethod(arg,param)->arg.instMethod(param)
Stream.of(1).map(String::valueOf).forEach(System.out::println);
构造器ClzName::new(arg) ->new ClzName(arg)
Stream.of("a").map(String::new).forEach(System.out::println);

二、 流计算

在Java8中引入Stream;流单个操作本身不是很强大,它的强大之处在于可以将各种操作组合在一起构建一个复杂的流处理l

1.流与集合

  流的中心思想是延迟计算,只有需要的时候才计算。流与集合的不同之处在于流不存储值,流的目的是处理值而不是存储值;集合的目的是存储值。

2.构建流

除Java中提供了IntStream,LongStream,DoubleStream 三个原生流外,

除了上述方法以外,java.util.stream.Stream类也提供了静态方法,如:

Stream.empty(); Stream.of() 

2.1通过数组创建流

     java.util.Arrays中提供的静态方法stream(T[])可以通过数组创建流,也可以使用Stream接口提供的静态方法Stream.of(T[])创建流,我们通过代码可以发现of方法也是调用Arrays.stream

 public static Stream of(T... values) {
        return Arrays.stream(values);
    }

2.2通过集合类创建流

java.util.Collection中提供的默认方法是我们平时最常用生成流的方式;其中parallelStream方法表示生产并行流。

 default Stream stream() {
        return StreamSupport.stream(spliterator(), false);
    }

   
    
    default Stream parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }

示例代码

 Stream stream = Arrays.asList(1, 2, 3).stream();
        Set sets=new HashSet<>();
        sets.add(1);
        sets.add(2);
        sets.add(3);
        sets.stream();

2.3创建持续流

在Stream中提供了iterator方法,可以根据传入的种子和一个函数式接口创建一个连续流,如下问代码所示,生成一个从1开始自增的流

       Stream.iterate(0,i->i+1).forEach(System.out::println);

除了iterator方法外也可以通过generate创建一个常量流

       Stream.generate(()->1).forEach(System.out::println);

3.流处理

一个标准的流处理包含以下三个部分:

  1. 流创建
  2. 流操作
  3. 流终止处理

其中流创建和流终止是必备可少的两个部分,上文也说到流的核心思想就是延迟处理,如果没有终止操作流是不会做任何处理的。流的终止操作可以分为以下几种

  1. 匹配
  2. 搜索
  3. 汇聚
  4. 收集
  5. 副作用

下文会进行详细介绍。

3.1过滤
Stream filter(Predicate predicate);是Stream提供的一个可以选择地处理元素的方法,仅仅处理输入流中满足predicate条件的元素。如下图所示,输入流为[1,2,3,4,5,6];predicate 是p%2==0,那么经过filter处理后的结果是2,4,6

3.2映射

 方法map会通过提供的Function转换每个流元素

     Stream map(Function mapper);

如下图:将[1,2,3,4,5,6]转换为字符串 

除了上述这种简单的映射外还有一种一对多的映射操作flatMap

     Stream flatMap(Function> mapper);

 如果所示,输入流是中的元素是一个collection,经过flatMap操作以后,将其平铺到一个流中。

3.3调试

   流处理带来便利的同时也有不便之处,对于中间执行操作的参数很难调试;Stream提供了一个peek操作,它输入和输出流的元素以及顺序相同,我们可以通过它来打印调试信息

       Arrays.asList(1,4,8).stream().peek(System.out::println).collect(Collectors.toList());

3.4排序

        在上文中的排序可以使用Stream提供的sort方法进行排序

       Arrays.asList(1,4,8).stream().peek(System.out::println).sorted(Integer::compareTo).collect(Collectors.toList());

3.5去重

   Stream提供了distinct方法进行去重操作

3.6截断

 Stream提供了skip()和limit()两个方法用于流的截断处理,skip()是丢掉前n的元素保留剩余元素,而limit则是保留前n个元素;如下代码输出的结果是[8,10]

        System.out.println(Arrays.asList(1,4,8,10).stream().skip(2).collect(Collectors.toList()));

而这段代码输出的结果是[1,4]

        System.out.println(Arrays.asList(1,4,8,10).stream().limit(2).collect(Collectors.toList()));

3.7匹配

   匹配是用于测试流中的某个元素或全部元素满足指定的predicate;anyMatch任意一个元素满足就返回true,allMatch全部元素都满足返回true,noneMatch全部都不满足返回true

boolean anyMatch(Predicate predicate);


boolean allMatch(Predicate predicate);

  
boolean noneMatch(Predicate predicate);

3.8搜索

 搜索主要有两个方法findFirst()和findAny(),区别就在于findFirst返回匹配的第一个元素,findAny()返回元素的位置就无从得知

    Optional findFirst();

    
    Optional findAny();

我们看这两个方法的返回值是Optional,他的主要方法有

  

3.9汇聚

 Steam提供了几个汇聚方法,见名知意,方法如下:

long count();

Optional max(Comparator comparator);

Optional min(Comparator comparator);

Optional max(Comparator comparator);

3.10收集

   收集元素是使用Stream.collection方法将元素积聚到可变容器中,这个是流操作中重要的部分,后续文章中将重点介绍

     R collect(Collector collector);

3.11副作用

Stream提供了可以替代迭代器操作的方法foreach

    void forEach(Consumer action);

    void forEachOrdered(Consumer action);


总结

本文主要对流与操作做了一个总体的介绍,后续将详细介绍流的收集与汇聚

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/996050.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号