热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

你真的开始用JDK8了吗?(下)

上篇文章中,看到了JDK8中的Optional和LambdaExpressions带来编程上的改变,甚至编程思维的改变。接下来我们继续看JDK8的Stream和Interfaced

上篇文章中,看到了JDK8中的Optional和Lambda Expressions带来编程上的改变,甚至编程思维的改变。接下来我们继续看JDK8的Stream和Interface default method给我们带来的改变

Stream

Stream也是JAVA8的一大特点,这里的Stream和IO的那个Stream不同,它提供了对集合操作的增强,极大的提高了操作集合对象的便利性。下面我们就通过一个示例来看,使用Stream给我们带来哪些改变。

有一批学生考试数据,包括学生ID,班级ID,学科,分数。来计算如下指标

  1. 找出所有语文科目,分数大于60分的学生
  2. 找出语文科目,排名第一的学生
  3. 计算学生ID为10的学生的总分
  4. 所有学生按照总分从大到小

在JDK8之前,实现以上功能也非常简单的,相信对于一个刚刚学习Java的工程师来说,也很容易实现。不妨大家给自己设定一个限制,如何使用最少的代码实现以上功能。这里留作一个问题思考,下面我们使用Stream API来实现这些需求.

筛选:filter用法

找出所有语文科目,分数大于60分的学生

studentScores.stream()
.filter(s -> "语文".equals(s.getSubject()) && s.getScore() >= 60f)
.collect(Collectors.toList())
.forEach(System.out::println);

排序:sorted用法

找出语文科目,排名第一的学生

Optional studentScore = studentScores.stream()
.filter(s -> "语文".equals(s.getSubject()))
.sorted((s1, s2) -> s1.getScore() > s2.getScore() ? -1 : 1)
.findFirst();
if (studentScore.isPresent()) {
System.out.println(studentScore.get());
}

统计计算:reduce

计算学生ID为10的学生的总分

Double total = studentScores.stream()
.filter(s -> s.getStudentId() == 10)
.mapToDouble(StudentScore::getScore)
.reduce(0, Double::sum);
System.out.println(total);
分组统计:Collectors

所有学生按照总分从大到小

studentScores.stream()
.collect(Collectors.groupingBy(StudentScore::getStudentId
, Collectors.summingDouble(StudentScore::getScore)))
.entrySet()
.stream()
.sorted((o1, o2) -> o1.getValue() 1 : -1)
.forEach(System.out::println);

以上的示例已经包括了Stream API的大部分的功能。从以上可以看到,在进行计算时,总是需要使用在集合对象中使用stream()方法,先转成Stream然后在进行后面的操作,为什么不直接在集合类下直接实现如下操作呢?Stream和集合类有哪些区别?Oracle给出了如下说明

  1. Stream没有存储,它不是数据结构,并不保存数据。它可以像数组、生成器等数据源获取数据,通过一个计算流进行操作
  2. 在功能性质上,通过流的操作,不会修改数据源,比如,filter操作,是从集合的流上获取一个新的流,而不是将过滤掉的元素从集合上删除
  3. 延迟计算,许多流式的计算像filter、map等,是通过懒式的实现。一个数据流操作包括三个基本步骤,数据源->数据转换->执行获取结果。每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象。数据转换的操作都是lazy的
  4. 可以支持无限的大小。虽然集合是有限的,但是流是可以支持无限大小的,像limit(n)或者findFirst可以让无限的流操作在有限的时间内完成
  5. 流的元素只能在一次创建中被访问到一次,像Iterator一样,必须生成一个新的流来访问新的元素

Interface default method

在JDK8中,使用forEach方法可以直接遍历数组,当然们进入查看forEach查看源代码时,我们在Iterable接口可以看到如下代码:

default void forEach(Consumersuper T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}

这不是方法的实现么?是的,在接口里可以写实现了。在JDK8中为了支持新特性,必须对原有接口进行改造。需要在不破坏现有的架构情况下在接口里增加新方法。这也是JAVA8引入Default method的原因。但是引入Default method之后,需要思考两个问题:

和抽象类区别

当接口有了default method 之后,接口看起来和抽象性是一样的,但是他们两个在Java8中还是有区别的。

抽象类,有自己的构造方法,并且可以定义自己的数据结构,但是默认方法只能调用接口时使用,并不会涉及到特定接口实现类的状态。具体使用接口还是抽象类还需要根据具体业务场景来界定

接口的多继承问题

在java中可以支持多继承,如果两个接口实现了同样的默认方法,那么应该使用哪个呢?

比如:

public interface DemoA {

default void test() {
System.out.println("I'm DemoA.");
}
}

public interface DemoB {

default void test() {
System.out.println("I'm DemoB.");
}
}

如果一个DemoImpl继承以上两个接口,代码如下:

public class DemoImpl implements DemoA, DemoB {
}

这时,IDE会在DemoImpl下面有一条红线,提示不能继承在DemoA和DemoB中的test方法,需要实现该方法

public class DemoImpl implements DemoA, DemoB {
@Override
public void test() {
DemoB.super.test();
DemoA.super.test();;
}
}

实现该方法,和其他方式类似,你可以调用父类中的方法,也可以直接自己实现

Other features

除了以上的一些特性,JDK8中还支持了其他的一些特性值得关注

  1. 引入了新的Date-Time API(JSR 310)来改进时间、日期的处理。
  2. 引入新的Nashorn Javascript引擎,使得我们可以在JVM上开发和运行JS应用。
  3. 引入了Base64编码的支持
  4. 新增了支持数组的并行处理的parallelSort方法等等

欢迎关注我的公众号MyArtNote

MyArtNote


推荐阅读
  • 本文详细介绍了如何使用C#实现不同类型的系统服务账户(如Windows服务、计划任务和IIS应用池)的密码重置方法。 ... [详细]
  • OBS Studio自动化实践:利用脚本批量生成录制场景
    本文探讨了如何利用OBS Studio进行高效录屏,并通过脚本实现场景的自动生成。适合对自动化办公感兴趣的读者。 ... [详细]
  • Web动态服务器Python基本实现
    Web动态服务器Python基本实现 ... [详细]
  • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
  • 本文详细介绍了在Luat OS中如何实现C与Lua的混合编程,包括在C环境中运行Lua脚本、封装可被Lua调用的C语言库,以及C与Lua之间的数据交互方法。 ... [详细]
  • ASP.NET 进度条实现详解
    本文介绍了如何在ASP.NET中使用HTML和JavaScript创建一个动态更新的进度条,并通过Default.aspx页面进行展示。 ... [详细]
  • 本文探讨了如何在 Spring MVC 框架下,通过自定义注解和拦截器机制来实现细粒度的权限管理功能。 ... [详细]
  • 本文探讨了如何利用RxJS库在AngularJS应用中实现对用户单击和拖动操作的精确区分,特别是在调整区域大小的场景下。 ... [详细]
  • Zabbix自定义监控与邮件告警配置实践
    本文详细介绍了如何在Zabbix中添加自定义监控项目,配置邮件告警功能,并解决测试告警时遇到的邮件不发送问题。 ... [详细]
  • Docker安全策略与管理
    本文探讨了Docker的安全挑战、核心安全特性及其管理策略,旨在帮助读者深入理解Docker安全机制,并提供实用的安全管理建议。 ... [详细]
  • 本文详细介绍了如何在Oracle VM VirtualBox中实现主机与虚拟机之间的数据交换,包括安装Guest Additions增强功能,以及如何利用这些功能进行文件传输、屏幕调整等操作。 ... [详细]
  • 本文详细介绍了 `org.apache.tinkerpop.gremlin.structure.VertexProperty` 类中的 `key()` 方法,并提供了多个实际应用的代码示例。通过这些示例,读者可以更好地理解该方法在图数据库操作中的具体用途。 ... [详细]
  • 我的读书清单(持续更新)201705311.《一千零一夜》2006(四五年级)2.《中华上下五千年》2008(初一)3.《鲁滨孙漂流记》2008(初二)4.《钢铁是怎样炼成的》20 ... [详细]
  • 近期尝试从www.hub.sciverse.com网站通过编程手段获取数据时遇到问题,起初尝试使用WebBrowser控件进行数据抓取,但发现使用GET方法翻页时,返回的HTML代码始终相同。进一步探究后了解到,该网站的数据是通过Ajax异步加载的,可通过HTTP查看详细的JSON响应。 ... [详细]
  • 问题场景用Java进行web开发过程当中,当遇到很多很多个字段的实体时,最苦恼的莫过于编辑字段的查看和修改界面,发现2个页面存在很多重复信息,能不能写一遍?有没有轮子用都不如自己造。解决方式笔者根据自 ... [详细]
author-avatar
茶不离
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有