搜索
首页Javajava教程解读Java8新特性--lambda的作用

解读Java8新特性--lambda的作用

Jun 17, 2017 pm 02:11 PM
java8作用特性解读

我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值。现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析Java集合里面的批量数据操作解开lambda最强作用的神秘面纱。

我们期待了很久lambda为java带来闭包的概念,但是如果我们不在集合中使用它的话,就损失了很大价值。现有接口迁移成为lambda风格的问题已经通过default methods解决了,在这篇文章将深入解析Java集合里面的批量数据操作(bulk operation),解开lambda最强作用的神秘面纱。

1.关于JSR335

JSR是Java Specification Requests的缩写,意思是Java 规范请求,Java 8 版本的主要改进是 Lambda 项目(JSR 335),其目的是使 Java 更易于为多核处理器编写代码。

2.外部VS内部迭代

以前Java集合是不能够表达内部迭代的,而只提供了一种外部迭代的方式,也就是for或者while循环


List persons = asList(new Person("Joe"), new Person("Jim"), new Person("John"));
for (Person p : persons) {
 p.setLastName("Doe");
}

上面的例子是我们以前的做法,也就是所谓的外部迭代,循环是固定的顺序循环。在现在多核的时代,如果我们想并行循环,不得不修改以上代码。效率能有多大提升还说定,且会带来一定的风险(线程安全问题等等)。 

要描述内部迭代,我们需要用到Lambda这样的类库,下面利用lambda和Collection.forEach重写上面的循环 


persons.forEach(p->p.setLastName("Doe"));

现在是由jdk 库来控制循环了,我们不需要关心last name是怎么被设置到每一个person对象里面去的,库可以根据运行环境来决定怎么做,并行,乱序或者懒加载方式。这就是内部迭代,客户端将行为p.setLastName当做数据传入api里面。 内部迭代其实和集合的批量操作并没有密切的联系,借助它我们感受到语法表达上的变化。真正有意思的和批量操作相关的是新的流(stream)API。新的java.util.stream包已经添加进JDK 8了。

3.Stream API

流(Stream)仅仅代表着数据流,并没有数据结构,所以他遍历完一次之后便再也无法遍历(这点在编程时候需要注意,不像Collection,遍历多少次里面都还有数据),它的来源可以是Collection、array、io等等。

3.1中间与终点方法

流作用是提供了一种操作大数据接口,让数据操作更容易和更快。它具有过滤、映射以及减少遍历数等方法,这些方法分两种:中间方法和终端方法,“流”抽象天生就该是持续的,中间方法永远返回的是Stream,因此如果我们要获取最终结果的话,必须使用终点操作才能收集流产生的最终结果。区分这两个方法是看他的返回值,如果是Stream则是中间方法,否则是终点方法。

简单介绍下几个中间方法(filter、map)以及终点方法(collect、sum)

3.1.1Filter

在数据流中实现过滤功能是首先我们可以想到的最自然的操作了。Stream接口暴露了一个filter方法,它可以接受表示操作的Predicate实现来使用定义了过滤条件的lambda表达式


List persons = …
Stream personsOver18 = persons.stream().filter(p -> p.getAge() > 18);//过滤18岁以上的人

3.1.2Map

假使我们现在过滤了一些数据,比如转换对象的时候。Map操作允许我们执行一个Function的实现(Function43ca9160a1fbc6e1e17f36fac17e2094的泛型T,R分别表示执行输入和执行结果),它接受入参并返回。首先,让我们来看看怎样以匿名内部类的方式来描述它:


Stream adult= persons
    .stream()
    .filter(p -> p.getAge() > 18)
    .map(new Function() {
     @Override
     public Adult apply(Person person) {
      return new Adult(person);//将大于18岁的人转为成年人
     }
    });

现在,把上述例子转换成使用lambda表达式的写法:


Stream map = persons.stream()
     .filter(p -> p.getAge() > 18)
     .map(person -> new Adult(person));

3.1.3Count

count方法是一个流的终点方法,可使流的结果最终统计,返回int,比如我们计算一下满足18岁的总人数


int countOfAdult=persons.stream()
      .filter(p -> p.getAge() > 18)
      .map(person -> new Adult(person))
      .count();

3.1.4Collect

collect方法也是一个流的终点方法,可收集最终的结果


List adultList= persons.stream()
      .filter(p -> p.getAge() > 18)
      .map(person -> new Adult(person))
      .collect(Collectors.toList());

或者,如果我们想使用特定的实现类来收集结果:


List adultList = persons
     .stream()
     .filter(p -> p.getAge() > 18)
     .map(person -> new Adult(person))
     .collect(Collectors.toCollection(ArrayList::new));

篇幅有限,其他的中间方法和终点方法就不一一介绍了,看了上面几个例子,大家明白这两种方法的区别即可,后面可根据需求来决定使用。

3.2顺序流与并行流

每个Stream都有两种模式:顺序执行和并行执行。

顺序流:


List <Person> people = list.getStream.collect(Collectors.toList());

并行流:


List <Person> people = list.getStream.parallel().collect(Collectors.toList());

顾名思义,当使用顺序方式去遍历时,每个item读完后再读下一个item。而使用并行去遍历时,数组会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。

3.2.1并行流原理:


List originalList = someData;
split1 = originalList(0, mid);//将数据分小部分
split2 = originalList(mid,end);
new Runnable(split1.process());//小部分执行操作
new Runnable(split2.process());
List revisedList = split1 + split2;//将结果合并

大家对hadoop有稍微了解就知道,里面的 MapReduce  本身就是用于并行处理大数据集的软件框架,其 处理大数据的核心思想就是大而化小,分配到不同机器去运行map,最终通过reduce将所有机器的结果结合起来得到一个最终结果,与MapReduce不同,Stream则是利用多核技术可将大数据通过多核并行处理,而MapReduce则可以分布式的。

3.2.2顺序与并行性能测试对比

如果是多核机器,理论上并行流则会比顺序流快上一倍,下面是测试代码


long t0 = System.nanoTime();

  //初始化一个范围100万整数流,求能被2整除的数字,toArray()是终点方法

  int a[]=IntStream.range(0, 1_000_000).filter(p -> p % 2==0).toArray();

  long t1 = System.nanoTime();

  //和上面功能一样,这里是用并行流来计算

  int b[]=IntStream.range(0, 1_000_000).parallel().filter(p -> p % 2==0).toArray();

  long t2 = System.nanoTime();

  //我本机的结果是serial: 0.06s, parallel 0.02s,证明并行流确实比顺序流快

  System.out.printf("serial: %.2fs, parallel %.2fs%n", (t1 - t0) * 1e-9, (t2 - t1) * 1e-9);

3.3关于Folk/Join框架

应用硬件的并行性在java 7就有了,那就是 java.util.concurrent 包的新增功能之一是一个 fork-join 风格的并行分解框架,同样也很强大高效,有兴趣的同学去研究,这里不详谈了,相比Stream.parallel()这种方式,我更倾向于后者。

4.总结

如果没有lambda,Stream用起来相当别扭,他会产生大量的匿名内部类,比如上面的3.1.2map例子,如果没有default method,集合框架更改势必会引起大量的改动,所以lambda+default method使得jdk库更加强大,以及灵活,Stream以及集合框架的改进便是最好的证明。

以上是解读Java8新特性--lambda的作用的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Go语言如何实现国密SM4和SM2算法的加解密以及互联互通?Go语言如何实现国密SM4和SM2算法的加解密以及互联互通?Apr 19, 2025 pm 06:27 PM

Go语言实现国密SM4和SM2加解密本文将详细介绍如何使用Go语言实现国密SM4和SM2算法的加解密流程,以满足与Java应�...

在Python项目中是否需要进行分层?在Python项目中是否需要进行分层?Apr 19, 2025 pm 06:24 PM

在Python项目中是否需要分层?最近我在学习Python时,注意到Django开源项目中,很多都在views函数里编写了大量的�...

如何使用MapStruct简化系统对接中的字段映射问题?如何使用MapStruct简化系统对接中的字段映射问题?Apr 19, 2025 pm 06:21 PM

系统对接中的字段映射处理在进行系统对接时,常常会遇到一个棘手的问题:如何将A系统的接口字段有效地映�...

IntelliJ IDEA是如何通过JavaAgent和RMI技术识别Spring Boot项目的端口号的?IntelliJ IDEA是如何通过JavaAgent和RMI技术识别Spring Boot项目的端口号的?Apr 19, 2025 pm 06:18 PM

IntelliJIDEA如何识别SpringBoot项目的端口号?在使用IntelliJIDEAUltimate版本启动Spring...

高效编程:如何才能找到可靠的代码工具和资源?高效编程:如何才能找到可靠的代码工具和资源?Apr 19, 2025 pm 06:15 PM

高效编程:寻找可靠的代码工具和资源很多程序员都渴望找到便捷的代码工具网站,以提高效率,避免在海量信...

JWT能否实现动态权限变更?与Session机制有何区别?JWT能否实现动态权限变更?与Session机制有何区别?Apr 19, 2025 pm 06:12 PM

关于JWT和Session的困惑与解答许多初学者在学习JWT和Session时,常常会对其本质和适用场景感到困惑。本文将围绕J...

Windows Server 2019防火墙如何正确配置才能支持WebSocket通信?Windows Server 2019防火墙如何正确配置才能支持WebSocket通信?Apr 19, 2025 pm 06:09 PM

WindowsServer2019防火墙与WebSocket通信问题详解在使用SpringBoot开发的Jar程序部署于WindowsServer2019...

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境