Java8 Stream 的最佳实践

java8stream提供了对于集合类的流失处理,其具有以下特点:

Lazy Evaluation(长度可以无限)

只能使用一次

内部迭代

Lazy Evaluation类似函数式中的LazyList,只有在需要时才去求值。减少了内存消耗,Java中可以用Iterator模拟。只有在进行终端操作时,stream才会执行。但是这个延迟计算不能保证流中的某个值单独延迟,需要时单独分配资源。

内部迭代的意思是我们告诉程序要实现的功能,迭代由程序自己控制。如filter时,我们只提供Predicate,而不是自己写for循环,至于程序自己是如何实现过滤数据的,我们并不关心。可能随着stream类库的迭代,实现效率会逐步提升。PS:新版本的Java类库String终于可以直接拼串了 😂,而且性能很好。

使用Stream的原则:

可读性、bugfree、短

// 读入数据,笔试用
Scanner sc = new Scanner(System.in);
String ss = sc.nextLine();
int[] nums = Arrays.stream(ss.split("\\s")).mapToInt(Integer::valueOf).toArray();

// flatMap只使用一次
// 这个例子来自于On Java 8
// 字符串打散,注意不要打散成char
// 常见的模式(方法返回流)
public static Stream stream(String filePath) throws Exception {
    return Files.lines(Paths.get(filePath))
    .skip(1) // First (comment) line
    .flatMap(line ->
    Pattern.compile("\\W+").splitAsStream(line));
}

// 一对多关系,保存到数据库,命令式编程需要两层for循环
List roles = users.stream().flatMap(user -> user.getRoles().stream()).collect(toList());
saveBatch(roles);

// 生成随机数组
int[] nums = new Random().ints(0, 100).limit(10).toArray();

// optional流的处理
stream1.filter(Optional::isPresent).map(Optional::get).collect(toList());
stream2.map(opt -> opt.orElse(defaultValue)).collect(toList());

// forEach
stream3.forEach(System.out::println);

// 生成Map,这种最终操作我后面会发文章详细分析Collectors工具类
Map idToUserMap = users.stream().collect(toMap(User::getId, it -> it));

// 获取角色到用户的映射(一对多)
HashMultiMap roleIdToUsersMap = userVos.stream().collect(toMultiMap(UserVo::getRoleId, UserVo::getUser, HashMultimap::create));

// 分组
Map> usersByLevelMap = users.collect(groupingBy(User::getLevel));

// 字符串拼接
subscriptions.stream().map(Object::toString).collect(joining(",", "(", ")"));

// 参数校验
boolean validated = request.getResources().stream().allMatch(authorities::contains);
if (!validated) throw ...

IntStream::sum, max, min, average, count...

// 教学意义
质数流,完全数流...

比如你需要一个字符串匹配算法,需要自己实现一些特殊功能,先写出暴力匹配,之后再优化。

比如我想获取一个前十名的排行榜,我不必在自己编写优先队列,或者使用其他类库。当需要优化时,再考虑优化。

// 至少我们可以确定:使用stream的内部迭代中时间复杂度最多是nlogn。
Comparator compScore = Comparator.comparingDouble(User::getScore).reversed();
List top10 = users.stream().sorted(compScore).limit(10).collect(toList());

毕竟Java不是纯函数式的语言,还要前向兼容,所以只能部分利用函数式的思想。以下这些做法在开发中应该避免。

Original: https://www.cnblogs.com/dahua-dijkstra/p/16249879.html
Author: 大华dijkstra
Title: Java8 Stream 的最佳实践

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/620356/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • C# 线程手册 第七章 网络和线程

    在本书的之前章节,我们已经深入地了解了C#.NET 中的线程并探讨了多线程编程中的不同概念和技术。现在你已经是一个线程专家啦,我们将要使用C#实现一个简单的多线程客户端-服务端程序…

    Java 2023年5月29日
    0149
  • ZXing二维码解析&精度提高一瞥

    报表中含有单号二维码,纸质单据经扫描仪扫描为图片后,使用 com.google.zxing解析二维码生成单号供程序使用。在实际使用过程中发现二维码解析时而有失败的情况,对扫描的单据…

    Java 2023年6月5日
    080
  • RocketMQ:Docker构建部署RocketMQ:4.9.2

    1.1 创建Dockerfile文件(Java8版本RocketMQ4.8.0先看下方3.3内容) 编辑Dockerfile文件, vim Dockerfile-namesrv 内…

    Java 2023年6月7日
    082
  • Springboot整合RocketMQ简单使用

    简单研究下Springboot 整合RocketMQ。 使用的是Apache的rocketmq-spring-boot-starter 1. 初始化项目 pom 文件

    Java 2023年5月30日
    0105
  • JavaWeb-Tomcat阀

    Filter的功能之一就是预处理客户请求,而 Tomcat阀是对 Catalina容器接收到的 HTTP请求进行预处理. 过滤器实在 Servlet规范中提出来的,因此适用于所有的…

    Java 2023年5月29日
    086
  • 面向对象和函数式

    阅读前,请先封印以下能力:类、闭包、继承&多态、高阶函数…… 现在,你只会全局变量和函数,开始写一个带 cache 的 fibonacci。 con…

    Java 2023年6月16日
    076
  • 【转】【数学】判断一个点是否在一个多边形里面

    “判断一个点是否在一个多边形里”,一开始以为是个挺难的问题,但Google了一下之后发现其实蛮简单,所用到的算法叫做”Ray-casting A…

    Java 2023年5月29日
    0101
  • RocketMQ的push消费方式实现的太聪明了

    大家好,我是三友,我又来了~~ 最近仍然畅游在RocketMQ的源码中,这几天刚好翻到了消费者的源码,发现RocketMQ的对于push消费方式的实现简直太聪明了,所以趁着我脑子里…

    Java 2023年6月16日
    0126
  • mybatis缓存

    加上flushCache=”true”后,再次运行结果如下 2.二级缓存 mybatis的二级缓存默认开启,但真正使用需要在mapper文件中添加相应的缓存…

    Java 2023年6月9日
    078
  • 解决SpringBoot与web前端下划线与驼峰不同参数命名规则参数无法接收问题

    有时候我们前端参数名称用的下划线,但是后台接收一般都用驼峰命名,这样就会导致前端参数无法接收到问题 加个配置 这样就会自动转换接收了,但是后台返回给前端的也会变成下划线的参数命名方…

    Java 2023年5月30日
    0160
  • 互联网技术部门该如何管理

    一、敏捷开发 1.快速开发、快速迭代。 2.组件式开发,避免重复造轮子。 3.制定代码标准。 4.并行开发,高效配合。 5.单元测试必须覆盖所有核心业务。 二、DevOps流程建立…

    Java 2023年6月16日
    090
  • CRLF 漏洞学习和工具使用

    原理 CRLF 指的是回车符(CR,ASCII 13,\r,%0d) 和换行符(LF,ASCII 10,\n,%0a),操作系统就是根据这个标识来进行换行的。但是如果对输入过滤不严…

    Java 2023年6月6日
    092
  • 封装RabbitTemplate,使用自定义消息转换器

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月7日
    071
  • day03-MySQL基础知识02

    MySQL基础知识02 4.CRUD 数据库CRUD语句:增(create)、删(delete)、改(update)、查(Retrieve) Insert 语句 (添加数据) Up…

    Java 2023年6月15日
    084
  • The valid characters are defined in RFC 7230 and RFC 3986

    The valid characters are defined in RFC 7230 and RFC 3986 1.异常截图 2.原因说明 ​ 导致上述问题是因为tomcat自…

    Java 2023年6月8日
    0106
  • 顺序存储二叉树

    顺序存储二叉树的概念 从数据存储来看,数组存储方式和树的存储方式可以相互转换,即 数组可以转换成树, 树也可以转换成数组, 看下面的示意图。 要求: 右图的二叉树的结点,要求以数组…

    Java 2023年6月15日
    096
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球